Compare commits

...

19 Commits

Author SHA1 Message Date
semantic-release-bot
8dda8988ef chore(release): 4.10.0-dev.3 [skip ci]
# [4.10.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v4.10.0-dev.2...v4.10.0-dev.3) (2024-06-08)

### Features

* **Boost For Reddit:** Add `Fix /s/ links` patch ([#3154](https://github.com/ReVanced/revanced-patches/issues/3154)) ([b575fc6](b575fc68ff))
2024-06-08 16:33:11 +00:00
Yan
b575fc68ff feat(Boost For Reddit): Add Fix /s/ links patch (#3154)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2024-06-08 18:31:18 +02:00
semantic-release-bot
c979e92676 chore(release): 4.10.0-dev.2 [skip ci]
# [4.10.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.10.0-dev.1...v4.10.0-dev.2) (2024-06-08)

### Bug Fixes

* **YouTube Music:** Rename `Minimized playback` to `Remove background playback restrictions` ([#3315](https://github.com/ReVanced/revanced-patches/issues/3315)) ([b78b7cf](b78b7cfe6c))
* **YouTube:** Rename `Minimized playback` to `Remove background playback restrictions` ([#3314](https://github.com/ReVanced/revanced-patches/issues/3314)) ([4919cba](4919cba478))
2024-06-08 08:37:57 +00:00
LisoUseInAIKyrios
b78b7cfe6c fix(YouTube Music): Rename Minimized playback to Remove background playback restrictions (#3315) 2024-06-08 11:35:44 +03:00
LisoUseInAIKyrios
4919cba478 fix(YouTube): Rename Minimized playback to Remove background playback restrictions (#3314) 2024-06-08 11:35:20 +03:00
semantic-release-bot
1d46b95698 chore(release): 4.10.0-dev.1 [skip ci]
# [4.10.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.9.0...v4.10.0-dev.1) (2024-06-07)

### Features

* **YouTube - Miniplayer:** Rename `Tablet mini player` and allow selecting the style of the in-app miniplayer ([#3302](https://github.com/ReVanced/revanced-patches/issues/3302)) ([70013d8](70013d813b))
2024-06-07 22:50:16 +00:00
LisoUseInAIKyrios
70013d813b feat(YouTube - Miniplayer): Rename Tablet mini player and allow selecting the style of the in-app miniplayer (#3302)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2024-06-08 01:48:12 +03:00
KobeW50
8a33fe9986 docs: Fix broken link (#3313)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2024-06-07 22:20:07 +02:00
LisoUseInAIKyrios
ee21a2bb91 chore(YouTube - Spoof client): Update iOS summary disclaimer 2024-06-04 06:43:18 +03:00
semantic-release-bot
ea67466bd5 chore(release): 4.9.0 [skip ci]
# [4.9.0](https://github.com/ReVanced/revanced-patches/compare/v4.8.3...v4.9.0) (2024-06-02)

### Bug Fixes

* **YouTube - Spoof client:** Allow swipe gestures to enter/exit fullscreen when spoofing with `Android VR` client ([#3259](https://github.com/ReVanced/revanced-patches/issues/3259)) ([ea1deb6](ea1deb630e))
* **YouTube - Spoof client:** Restore playback speed menu when spoofing to an iOS client ([61401c9](61401c9ea4))

### Features

* **Messenger:** Add `Hide inbox subtabs` patch ([#3163](https://github.com/ReVanced/revanced-patches/issues/3163)) ([a331f0a](a331f0a30b))
* **YouTube - Hide layout components:** Disable like / subscribe button glow animation ([#3265](https://github.com/ReVanced/revanced-patches/issues/3265)) ([367a83a](367a83accd))
* **YouTube - Playback speed:** Add option to show speed dialog button in video player ([#3197](https://github.com/ReVanced/revanced-patches/issues/3197)) ([8e67cdc](8e67cdca55))
* **YouTube Music:** Support version `7.03` ([#3272](https://github.com/ReVanced/revanced-patches/issues/3272)) ([6c25c95](6c25c95747))
* **YouTube:** Support version `19.12`, `19.13`, `19.14`, `19.15` and `19.16` ([#3239](https://github.com/ReVanced/revanced-patches/issues/3239)) ([868f51d](868f51d992))
2024-06-02 17:43:45 +00:00
oSumAtrIX
320e039a9f chore: Merge branch dev to main (#3266) 2024-06-02 19:41:49 +02:00
semantic-release-bot
6b9c13d92c chore(release): 4.9.0-dev.7 [skip ci]
# [4.9.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v4.9.0-dev.6...v4.9.0-dev.7) (2024-06-02)

### Features

* **YouTube - Playback speed:** Add option to show speed dialog button in video player ([#3197](https://github.com/ReVanced/revanced-patches/issues/3197)) ([8e67cdc](8e67cdca55))
2024-06-02 15:50:45 +00:00
MarcaD
8e67cdca55 feat(YouTube - Playback speed): Add option to show speed dialog button in video player (#3197)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2024-06-02 17:48:35 +02:00
semantic-release-bot
32c5fa4d04 chore(release): 4.9.0-dev.6 [skip ci]
# [4.9.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v4.9.0-dev.5...v4.9.0-dev.6) (2024-06-02)

### Bug Fixes

* **YouTube - Spoof client:** Restore playback speed menu when spoofing to an iOS client ([61401c9](61401c9ea4))
2024-06-02 15:46:01 +00:00
oSumAtrIX
61401c9ea4 fix(YouTube - Spoof client): Restore playback speed menu when spoofing to an iOS client 2024-06-02 17:43:41 +02:00
semantic-release-bot
cd42182d6b chore(release): 4.9.0-dev.5 [skip ci]
# [4.9.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v4.9.0-dev.4...v4.9.0-dev.5) (2024-06-01)

### Features

* **YouTube:** Support version `19.12`, `19.13`, `19.14`, `19.15` and `19.16` ([#3239](https://github.com/ReVanced/revanced-patches/issues/3239)) ([868f51d](868f51d992))
2024-06-01 18:10:28 +00:00
LisoUseInAIKyrios
868f51d992 feat(YouTube): Support version 19.12, 19.13, 19.14, 19.15 and 19.16 (#3239)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2024-06-01 22:08:09 +04:00
semantic-release-bot
efbe314e0d chore(release): 4.9.0-dev.4 [skip ci]
# [4.9.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v4.9.0-dev.3...v4.9.0-dev.4) (2024-06-01)

### Features

* **Messenger:** Add `Hide inbox subtabs` patch ([#3163](https://github.com/ReVanced/revanced-patches/issues/3163)) ([a331f0a](a331f0a30b))
2024-06-01 17:27:18 +00:00
seaque
a331f0a30b feat(Messenger): Add Hide inbox subtabs patch (#3163)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2024-06-01 19:25:14 +02:00
125 changed files with 2059 additions and 676 deletions

View File

@@ -1,3 +1,70 @@
# [4.10.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v4.10.0-dev.2...v4.10.0-dev.3) (2024-06-08)
### Features
* **Boost For Reddit:** Add `Fix /s/ links` patch ([#3154](https://github.com/ReVanced/revanced-patches/issues/3154)) ([5fa9fd2](https://github.com/ReVanced/revanced-patches/commit/5fa9fd2dfef43838d7311a967a3e805256a5d116))
# [4.10.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.10.0-dev.1...v4.10.0-dev.2) (2024-06-08)
### Bug Fixes
* **YouTube Music:** Rename `Minimized playback` to `Remove background playback restrictions` ([#3315](https://github.com/ReVanced/revanced-patches/issues/3315)) ([3c31e55](https://github.com/ReVanced/revanced-patches/commit/3c31e55b13d9495e857f068f8cd2b4320112d763))
* **YouTube:** Rename `Minimized playback` to `Remove background playback restrictions` ([#3314](https://github.com/ReVanced/revanced-patches/issues/3314)) ([37d415b](https://github.com/ReVanced/revanced-patches/commit/37d415b53af4771d9c97a8b1c153be32bf3ac2e0))
# [4.10.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.9.0...v4.10.0-dev.1) (2024-06-07)
### Features
* **YouTube - Miniplayer:** Rename `Tablet mini player` and allow selecting the style of the in-app miniplayer ([#3302](https://github.com/ReVanced/revanced-patches/issues/3302)) ([5511736](https://github.com/ReVanced/revanced-patches/commit/5511736b0c5dd409db6a68db0f85e389bb95be47))
# [4.9.0](https://github.com/ReVanced/revanced-patches/compare/v4.8.3...v4.9.0) (2024-06-02)
### Bug Fixes
* **YouTube - Spoof client:** Allow swipe gestures to enter/exit fullscreen when spoofing with `Android VR` client ([#3259](https://github.com/ReVanced/revanced-patches/issues/3259)) ([5114900](https://github.com/ReVanced/revanced-patches/commit/5114900b1b5572c04ba6759eedab77f0a934b058))
* **YouTube - Spoof client:** Restore playback speed menu when spoofing to an iOS client ([95f290f](https://github.com/ReVanced/revanced-patches/commit/95f290f1139cc8679beecac53c623847668f885e))
### Features
* **Messenger:** Add `Hide inbox subtabs` patch ([#3163](https://github.com/ReVanced/revanced-patches/issues/3163)) ([24e4ebd](https://github.com/ReVanced/revanced-patches/commit/24e4ebd77ad0f349b479926bf3983b72c2683496))
* **YouTube - Hide layout components:** Disable like / subscribe button glow animation ([#3265](https://github.com/ReVanced/revanced-patches/issues/3265)) ([68d35ea](https://github.com/ReVanced/revanced-patches/commit/68d35eafc15513c23cd5220260023e7ec5b7978a))
* **YouTube - Playback speed:** Add option to show speed dialog button in video player ([#3197](https://github.com/ReVanced/revanced-patches/issues/3197)) ([ad00305](https://github.com/ReVanced/revanced-patches/commit/ad00305ff57d5e8041de7375bea7d3ad6f18c4e2))
* **YouTube Music:** Support version `7.03` ([#3272](https://github.com/ReVanced/revanced-patches/issues/3272)) ([d1ceca3](https://github.com/ReVanced/revanced-patches/commit/d1ceca39984f7933b28d81802d04bb3ead327595))
* **YouTube:** Support version `19.12`, `19.13`, `19.14`, `19.15` and `19.16` ([#3239](https://github.com/ReVanced/revanced-patches/issues/3239)) ([99b07e0](https://github.com/ReVanced/revanced-patches/commit/99b07e0e18574668f36bb3c962c8d11222114be4))
# [4.9.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v4.9.0-dev.6...v4.9.0-dev.7) (2024-06-02)
### Features
* **YouTube - Playback speed:** Add option to show speed dialog button in video player ([#3197](https://github.com/ReVanced/revanced-patches/issues/3197)) ([ad00305](https://github.com/ReVanced/revanced-patches/commit/ad00305ff57d5e8041de7375bea7d3ad6f18c4e2))
# [4.9.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v4.9.0-dev.5...v4.9.0-dev.6) (2024-06-02)
### Bug Fixes
* **YouTube - Spoof client:** Restore playback speed menu when spoofing to an iOS client ([95f290f](https://github.com/ReVanced/revanced-patches/commit/95f290f1139cc8679beecac53c623847668f885e))
# [4.9.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v4.9.0-dev.4...v4.9.0-dev.5) (2024-06-01)
### Features
* **YouTube:** Support version `19.12`, `19.13`, `19.14`, `19.15` and `19.16` ([#3239](https://github.com/ReVanced/revanced-patches/issues/3239)) ([99b07e0](https://github.com/ReVanced/revanced-patches/commit/99b07e0e18574668f36bb3c962c8d11222114be4))
# [4.9.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v4.9.0-dev.3...v4.9.0-dev.4) (2024-06-01)
### Features
* **Messenger:** Add `Hide inbox subtabs` patch ([#3163](https://github.com/ReVanced/revanced-patches/issues/3163)) ([24e4ebd](https://github.com/ReVanced/revanced-patches/commit/24e4ebd77ad0f349b479926bf3983b72c2683496))
# [4.9.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v4.9.0-dev.2...v4.9.0-dev.3) (2024-06-01)

View File

@@ -115,7 +115,7 @@ with the maintainers of ReVanced Patches. This will help you determine whether y
and whether it is worth your time to implement it
2. Development happens on the `dev` branch. Fork the repository and create your branch from `dev`
3. Commit your changes. In case you are contributing a new patch, make sure to follow the conventions for patches
described in the [documentation](https://github.com/ReVanced/revanced-patches/tree/docs/docs)
described in the [ReVanced Patcher documentation](https://github.com/ReVanced/revanced-patcher/tree/main/docs)
4. Submit a pull request to the `dev` branch of the repository and reference issues
that your pull request closes in the description of your pull request
5. Our team will review your pull request and provide feedback. Once your pull request is approved,

View File

@@ -277,20 +277,26 @@ public final class app/revanced/patches/memegenerator/misc/pro/UnlockProVersionP
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/messenger/ads/inbox/patch/HideInboxAdsPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/messenger/ads/inbox/patch/HideInboxAdsPatch;
public final class app/revanced/patches/messenger/inbox/HideInboxAdsPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/messenger/inbox/HideInboxAdsPatch;
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/messenger/inputfield/patch/DisableSwitchingEmojiToStickerPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/messenger/inputfield/patch/DisableSwitchingEmojiToStickerPatch;
public final class app/revanced/patches/messenger/inbox/HideInboxSubtabsPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/messenger/inbox/HideInboxSubtabsPatch;
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/messenger/inputfield/patch/DisableTypingIndicatorPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/messenger/inputfield/patch/DisableTypingIndicatorPatch;
public final class app/revanced/patches/messenger/inputfield/DisableSwitchingEmojiToStickerPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/messenger/inputfield/DisableSwitchingEmojiToStickerPatch;
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/messenger/inputfield/DisableTypingIndicatorPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/messenger/inputfield/DisableTypingIndicatorPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
@@ -397,6 +403,12 @@ public final class app/revanced/patches/music/misc/androidauto/BypassCertificate
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/music/misc/backgroundplayback/BackgroundPlaybackPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/music/misc/backgroundplayback/BackgroundPlaybackPatch;
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/misc/gms/Constants {
public static final field INSTANCE Lapp/revanced/patches/music/misc/gms/Constants;
}
@@ -523,6 +535,18 @@ public final class app/revanced/patches/reddit/ad/general/HideAdsPatch : app/rev
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public abstract class app/revanced/patches/reddit/customclients/BaseFixSLinksPatch : app/revanced/patcher/patch/BytecodePatch {
public fun <init> (Lapp/revanced/patcher/fingerprint/MethodFingerprint;Lapp/revanced/patcher/fingerprint/MethodFingerprint;Ljava/util/Set;Ljava/util/Set;)V
public synthetic fun <init> (Lapp/revanced/patcher/fingerprint/MethodFingerprint;Lapp/revanced/patcher/fingerprint/MethodFingerprint;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
protected abstract fun getIntegrationsClassDescriptor ()Ljava/lang/String;
protected final fun getResolveSLinkMethod ()Ljava/lang/String;
protected final fun getSetAccessTokenMethod ()Ljava/lang/String;
protected abstract fun patchNavigationHandler (Lapp/revanced/patcher/fingerprint/MethodFingerprintResult;Lapp/revanced/patcher/data/BytecodeContext;)V
protected abstract fun patchSetAccessToken (Lapp/revanced/patcher/fingerprint/MethodFingerprintResult;Lapp/revanced/patcher/data/BytecodeContext;)V
}
public abstract class app/revanced/patches/reddit/customclients/BaseSpoofClientPatch : app/revanced/patcher/patch/BytecodePatch {
public fun <init> (Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;Ljava/util/Set;Ljava/util/Set;Ljava/util/Set;)V
public synthetic fun <init> (Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;Ljava/util/Set;Ljava/util/Set;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
@@ -558,6 +582,14 @@ public final class app/revanced/patches/reddit/customclients/boostforreddit/api/
public fun patchUserAgent (Ljava/util/Set;Lapp/revanced/patcher/data/BytecodeContext;)V
}
public final class app/revanced/patches/reddit/customclients/boostforreddit/fix/slink/FixSLinksPatch : app/revanced/patches/reddit/customclients/BaseFixSLinksPatch {
public static final field INSTANCE Lapp/revanced/patches/reddit/customclients/boostforreddit/fix/slink/FixSLinksPatch;
}
public final class app/revanced/patches/reddit/customclients/boostforreddit/misc/integrations/IntegrationsPatch : app/revanced/patches/shared/misc/integrations/BaseIntegrationsPatch {
public static final field INSTANCE Lapp/revanced/patches/reddit/customclients/boostforreddit/misc/integrations/IntegrationsPatch;
}
public final class app/revanced/patches/reddit/customclients/infinityforreddit/api/SpoofClientPatch : app/revanced/patches/reddit/customclients/BaseSpoofClientPatch {
public static final field INSTANCE Lapp/revanced/patches/reddit/customclients/infinityforreddit/api/SpoofClientPatch;
public fun patchClientId (Ljava/util/Set;Lapp/revanced/patcher/data/BytecodeContext;)V
@@ -636,10 +668,12 @@ public final class app/revanced/patches/reddit/customclients/syncforreddit/detec
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/reddit/customclients/syncforreddit/fix/slink/FixSLinksPatch : app/revanced/patcher/patch/BytecodePatch {
public final class app/revanced/patches/reddit/customclients/syncforreddit/fix/slink/FixSLinksPatch : app/revanced/patches/reddit/customclients/BaseFixSLinksPatch {
public static final field INSTANCE Lapp/revanced/patches/reddit/customclients/syncforreddit/fix/slink/FixSLinksPatch;
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/reddit/customclients/syncforreddit/misc/integrations/IntegrationsPatch : app/revanced/patches/shared/misc/integrations/BaseIntegrationsPatch {
public static final field INSTANCE Lapp/revanced/patches/reddit/customclients/syncforreddit/misc/integrations/IntegrationsPatch;
}
public final class app/revanced/patches/reddit/layout/disablescreenshotpopup/DisableScreenshotPopupPatch : app/revanced/patcher/patch/BytecodePatch {
@@ -1522,6 +1556,12 @@ public final class app/revanced/patches/youtube/layout/hide/time/HideTimestampPa
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/youtube/layout/miniplayer/MiniplayerPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/youtube/layout/miniplayer/MiniplayerPatch;
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/layout/panels/popup/PlayerPopupPanelsPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/youtube/layout/panels/popup/PlayerPopupPanelsPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
@@ -1626,6 +1666,12 @@ public final class app/revanced/patches/youtube/misc/autorepeat/AutoRepeatPatch
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/youtube/misc/backgroundplayback/BackgroundPlaybackPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/youtube/misc/backgroundplayback/BackgroundPlaybackPatch;
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/misc/debugging/DebuggingPatch : app/revanced/patcher/patch/ResourcePatch {
public static final field INSTANCE Lapp/revanced/patches/youtube/misc/debugging/DebuggingPatch;
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
@@ -1834,6 +1880,12 @@ public final class app/revanced/patches/youtube/video/speed/PlaybackSpeedPatch :
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/youtube/video/speed/button/PlaybackSpeedButtonPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/youtube/video/speed/button/PlaybackSpeedButtonPatch;
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/video/speed/custom/CustomPlaybackSpeedPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/youtube/video/speed/custom/CustomPlaybackSpeedPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
@@ -1882,9 +1934,15 @@ public final class app/revanced/patches/yuka/misc/unlockpremium/UnlockPremiumPat
public final class app/revanced/util/BytecodeUtilsKt {
public static final fun containsWideLiteralInstructionValue (Lcom/android/tools/smali/dexlib2/iface/Method;J)Z
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 getException (Lapp/revanced/patcher/fingerprint/MethodFingerprint;)Lapp/revanced/patcher/patch/PatchException;
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;ILkotlin/jvm/functions/Function1;ILjava/lang/Object;)I
public static final fun indexOfFirstInstructionOrThrow (Lcom/android/tools/smali/dexlib2/iface/Method;ILkotlin/jvm/functions/Function1;)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 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 indexOfIdResource (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/String;)I
public static final fun indexOfIdResourceOrThrow (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/String;)I
public static final fun injectHideViewCall (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;IILjava/lang/String;Ljava/lang/String;)V

View File

@@ -1,4 +1,4 @@
org.gradle.parallel = true
org.gradle.caching = true
kotlin.code.style = official
version = 4.9.0-dev.3
version = 4.10.0-dev.3

View File

@@ -1,21 +1,21 @@
package app.revanced.patches.messenger.ads.inbox.patch
package app.revanced.patches.messenger.inbox
import app.revanced.util.exception
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.messenger.ads.inbox.fingerprints.LoadInboxAdsFingerprint
import app.revanced.patches.messenger.inbox.fingerprints.LoadInboxAdsFingerprint
import app.revanced.util.exception
@Patch(
name = "Hide inbox ads",
description = "Hides ads in inbox.",
compatiblePackages = [CompatiblePackage("com.facebook.orca")]
compatiblePackages = [CompatiblePackage("com.facebook.orca")],
)
@Suppress("unused")
object HideInboxAdsPatch : BytecodePatch(
setOf(LoadInboxAdsFingerprint)
setOf(LoadInboxAdsFingerprint),
) {
override fun execute(context: BytecodeContext) {
LoadInboxAdsFingerprint.result?.mutableMethod?.apply {
@@ -23,4 +23,3 @@ object HideInboxAdsPatch : BytecodePatch(
} ?: throw LoadInboxAdsFingerprint.exception
}
}

View File

@@ -0,0 +1,24 @@
package app.revanced.patches.messenger.inbox
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.messenger.inbox.fingerprints.CreateInboxSubTabsFingerprint
import app.revanced.util.exception
@Patch(
name = "Hide inbox subtabs",
description = "Hides Home and Channels tabs between active now tray and chats.",
compatiblePackages = [CompatiblePackage("com.facebook.orca")],
)
@Suppress("unused")
object HideInboxSubtabsPatch : BytecodePatch(
setOf(CreateInboxSubTabsFingerprint),
) {
// Set InboxSubtabsItemSupplierImplementation boolean attribute to false.
override fun execute(context: BytecodeContext) = CreateInboxSubTabsFingerprint.result?.mutableMethod
?.replaceInstruction(2, "const/4 v0, 0x0")
?: throw CreateInboxSubTabsFingerprint.exception
}

View File

@@ -0,0 +1,23 @@
package app.revanced.patches.messenger.inbox.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
import com.android.tools.smali.dexlib2.iface.value.StringEncodedValue
internal object CreateInboxSubTabsFingerprint : MethodFingerprint(
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
opcodes = listOf(
Opcode.CONST_4,
Opcode.INVOKE_VIRTUAL,
Opcode.RETURN_VOID,
),
customFingerprint = { methodDef, classDef ->
methodDef.name == "run" && classDef.fields.any any@{ field ->
if (field.name != "__redex_internal_original_name") return@any false
(field.initialValue as? StringEncodedValue)?.value == "InboxSubtabsItemSupplierImplementation\$onSubscribe\$1"
}
},
)

View File

@@ -1,4 +1,4 @@
package app.revanced.patches.messenger.ads.inbox.fingerprints
package app.revanced.patches.messenger.inbox.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
@@ -8,11 +8,10 @@ internal object LoadInboxAdsFingerprint : MethodFingerprint(
returnType = "V",
strings = listOf(
"ads_load_begin",
"inbox_ads_fetch_start"
"inbox_ads_fetch_start",
),
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
customFingerprint = { methodDef, _ ->
methodDef.definingClass == "Lcom/facebook/messaging/business/inboxads/plugins/inboxads/itemsupplier/InboxAdsItemSupplierImplementation;"
}
},
)

View File

@@ -1,6 +1,5 @@
package app.revanced.patches.messenger.inputfield.patch
package app.revanced.patches.messenger.inputfield
import app.revanced.util.exception
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
@@ -8,16 +7,17 @@ import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.messenger.inputfield.fingerprints.SwitchMessangeInputEmojiButtonFingerprint
import app.revanced.util.exception
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Patch(
name = "Disable switching emoji to sticker",
description = "Disables switching from emoji to sticker search mode in message input field.",
compatiblePackages = [CompatiblePackage("com.facebook.orca")]
compatiblePackages = [CompatiblePackage("com.facebook.orca")],
)
@Suppress("unused")
object DisableSwitchingEmojiToStickerPatch : BytecodePatch(
setOf(SwitchMessangeInputEmojiButtonFingerprint)
setOf(SwitchMessangeInputEmojiButtonFingerprint),
) {
override fun execute(context: BytecodeContext) {
SwitchMessangeInputEmojiButtonFingerprint.result?.let {
@@ -28,7 +28,7 @@ object DisableSwitchingEmojiToStickerPatch : BytecodePatch(
replaceInstruction(
setStringIndex,
"const-string v$targetRegister, \"expression\""
"const-string v$targetRegister, \"expression\"",
)
}
} ?: throw SwitchMessangeInputEmojiButtonFingerprint.exception

View File

@@ -1,22 +1,22 @@
package app.revanced.patches.messenger.inputfield.patch
package app.revanced.patches.messenger.inputfield
import app.revanced.util.exception
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.messenger.inputfield.fingerprints.SendTypingIndicatorFingerprint
import app.revanced.util.exception
@Patch(
name = "Disable typing indicator",
description = "Disables the indicator while typing a message.",
compatiblePackages = [CompatiblePackage("com.facebook.orca")]
compatiblePackages = [CompatiblePackage("com.facebook.orca")],
)
@Suppress("unused")
object DisableTypingIndicatorPatch : BytecodePatch(
setOf(SendTypingIndicatorFingerprint)
){
setOf(SendTypingIndicatorFingerprint),
) {
override fun execute(context: BytecodeContext) {
SendTypingIndicatorFingerprint.result?.mutableMethod?.replaceInstruction(0, "return-void")
?: throw SendTypingIndicatorFingerprint.exception

View File

@@ -1,50 +1,13 @@
package app.revanced.patches.music.layout.minimizedplayback
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.music.layout.minimizedplayback.fingerprints.BackgroundPlaybackDisableFingerprint
import app.revanced.patches.music.layout.minimizedplayback.fingerprints.KidsMinimizedPlaybackPolicyControllerFingerprint
import app.revanced.util.exception
import app.revanced.patches.music.misc.backgroundplayback.BackgroundPlaybackPatch
@Patch(
name = "Minimized playback",
description = "Unlocks options for picture-in-picture and background playback.",
compatiblePackages = [
CompatiblePackage(
"com.google.android.apps.youtube.music",
[
"6.45.54",
"6.51.53",
"7.01.53",
"7.02.52",
"7.03.52",
]
)
]
)
@Suppress("unused")
@Deprecated("This patch has been merged into BackgroundPlaybackPatch.")
object MinimizedPlaybackPatch : BytecodePatch(
setOf(
KidsMinimizedPlaybackPolicyControllerFingerprint,
BackgroundPlaybackDisableFingerprint,
),
dependencies = setOf(BackgroundPlaybackPatch::class),
) {
override fun execute(context: BytecodeContext) {
KidsMinimizedPlaybackPolicyControllerFingerprint.result?.mutableMethod?.addInstruction(
0,
"return-void",
) ?: throw KidsMinimizedPlaybackPolicyControllerFingerprint.exception
BackgroundPlaybackDisableFingerprint.result?.mutableMethod?.addInstructions(
0,
"""
const/4 v0, 0x1
return v0
""",
) ?: throw BackgroundPlaybackDisableFingerprint.exception
}
}
}

View File

@@ -0,0 +1,50 @@
package app.revanced.patches.music.misc.backgroundplayback
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.music.misc.backgroundplayback.fingerprints.BackgroundPlaybackDisableFingerprint
import app.revanced.patches.music.misc.backgroundplayback.fingerprints.KidsBackgroundPlaybackPolicyControllerFingerprint
import app.revanced.util.resultOrThrow
@Patch(
name = "Remove background playback restrictions",
description = "Removes restrictions on background playback.",
compatiblePackages = [
CompatiblePackage(
"com.google.android.apps.youtube.music",
[
"6.45.54",
"6.51.53",
"7.01.53",
"7.02.52",
"7.03.52",
]
)
]
)
@Suppress("unused")
object BackgroundPlaybackPatch : BytecodePatch(
setOf(
KidsBackgroundPlaybackPolicyControllerFingerprint,
BackgroundPlaybackDisableFingerprint,
),
) {
override fun execute(context: BytecodeContext) {
KidsBackgroundPlaybackPolicyControllerFingerprint.resultOrThrow().mutableMethod.addInstruction(
0,
"return-void",
)
BackgroundPlaybackDisableFingerprint.resultOrThrow().mutableMethod.addInstructions(
0,
"""
const/4 v0, 0x1
return v0
""",
)
}
}

View File

@@ -1,4 +1,4 @@
package app.revanced.patches.music.layout.minimizedplayback.fingerprints
package app.revanced.patches.music.misc.backgroundplayback.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint

View File

@@ -1,11 +1,11 @@
package app.revanced.patches.music.layout.minimizedplayback.fingerprints
package app.revanced.patches.music.misc.backgroundplayback.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 KidsMinimizedPlaybackPolicyControllerFingerprint : MethodFingerprint(
internal object KidsBackgroundPlaybackPolicyControllerFingerprint : MethodFingerprint(
"V",
AccessFlags.PUBLIC or AccessFlags.FINAL,
listOf("I", "L", "Z"),

View File

@@ -2,10 +2,11 @@ package app.revanced.patches.music.premium.backgroundplay
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patches.music.layout.minimizedplayback.MinimizedPlaybackPatch
@Deprecated("This patch has been merged into MinimizedPlaybackPatch.")
import app.revanced.patches.music.misc.backgroundplayback.BackgroundPlaybackPatch
@Deprecated("This patch has been merged into BackgroundPlaybackPatch.")
object BackgroundPlayPatch : BytecodePatch(
dependencies = setOf(MinimizedPlaybackPatch::class),
dependencies = setOf(BackgroundPlaybackPatch::class),
) {
override fun execute(context: BytecodeContext) {
}

View File

@@ -0,0 +1,49 @@
package app.revanced.patches.reddit.customclients
import app.revanced.patcher.PatchClass
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.fingerprint.MethodFingerprint
import app.revanced.patcher.fingerprint.MethodFingerprintResult
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.util.resultOrThrow
abstract class BaseFixSLinksPatch(
private val handleNavigationFingerprint: MethodFingerprint,
private val setAccessTokenFingerprint: MethodFingerprint,
compatiblePackages: Set<CompatiblePackage>,
dependencies: Set<PatchClass> = emptySet(),
) : BytecodePatch(
name = "Fix /s/ links",
fingerprints = setOf(handleNavigationFingerprint, setAccessTokenFingerprint),
compatiblePackages = compatiblePackages,
dependencies = dependencies,
) {
protected abstract val integrationsClassDescriptor: String
protected val resolveSLinkMethod =
"patchResolveSLink(Ljava/lang/String;)Z"
protected val setAccessTokenMethod =
"patchSetAccessToken(Ljava/lang/String;)V"
override fun execute(context: BytecodeContext) {
handleNavigationFingerprint.resultOrThrow().patchNavigationHandler(context)
setAccessTokenFingerprint.resultOrThrow().patchSetAccessToken(context)
}
/**
* Patch app's navigation handler to resolve /s/ links.
*
* @param context The current [BytecodeContext].
*
*/
protected abstract fun MethodFingerprintResult.patchNavigationHandler(context: BytecodeContext)
/**
* Patch access token setup in app to resolve /s/ links with an access token
* in order to bypass API bans when making unauthorized requests.
*
* @param context The current [BytecodeContext].
*/
protected abstract fun MethodFingerprintResult.patchSetAccessToken(context: BytecodeContext)
}

View File

@@ -0,0 +1,44 @@
package app.revanced.patches.reddit.customclients.boostforreddit.fix.slink
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.fingerprint.MethodFingerprintResult
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.reddit.customclients.BaseFixSLinksPatch
import app.revanced.patches.reddit.customclients.boostforreddit.fix.slink.fingerprints.GetOAuthAccessTokenFingerprint
import app.revanced.patches.reddit.customclients.boostforreddit.fix.slink.fingerprints.HandleNavigationFingerprint
import app.revanced.patches.reddit.customclients.boostforreddit.misc.integrations.IntegrationsPatch
@Suppress("unused")
object FixSLinksPatch : BaseFixSLinksPatch(
handleNavigationFingerprint = HandleNavigationFingerprint,
setAccessTokenFingerprint = GetOAuthAccessTokenFingerprint,
compatiblePackages = setOf(CompatiblePackage("com.rubenmayayo.reddit")),
dependencies = setOf(IntegrationsPatch::class),
) {
override val integrationsClassDescriptor = "Lapp/revanced/integrations/boostforreddit/FixSLinksPatch;"
override fun MethodFingerprintResult.patchNavigationHandler(context: BytecodeContext) {
mutableMethod.apply {
val urlRegister = "p1"
val tempRegister = "v1"
addInstructionsWithLabels(
0,
"""
invoke-static { $urlRegister }, $integrationsClassDescriptor->$resolveSLinkMethod
move-result $tempRegister
if-eqz $tempRegister, :continue
return $tempRegister
""",
ExternalLabel("continue", getInstruction(0)),
)
}
}
override fun MethodFingerprintResult.patchSetAccessToken(context: BytecodeContext) = mutableMethod.addInstruction(
3,
"invoke-static { v0 }, $integrationsClassDescriptor->$setAccessTokenMethod",
)
}

View File

@@ -0,0 +1,10 @@
package app.revanced.patches.reddit.customclients.boostforreddit.fix.slink.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
internal object GetOAuthAccessTokenFingerprint : MethodFingerprint(
strings = listOf("access_token"),
accessFlags = AccessFlags.PUBLIC.value,
returnType = "Ljava/lang/String",
customFingerprint = { _, classDef -> classDef.type == "Lnet/dean/jraw/http/oauth/OAuthData;" },
)

View File

@@ -0,0 +1,12 @@
package app.revanced.patches.reddit.customclients.boostforreddit.fix.slink.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
internal object HandleNavigationFingerprint : MethodFingerprint(
strings = listOf(
"android.intent.action.SEARCH",
"subscription",
"sort",
"period",
"boostforreddit.com/themes",
),
)

View File

@@ -0,0 +1,10 @@
package app.revanced.patches.reddit.customclients.boostforreddit.misc.integrations
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.misc.integrations.BaseIntegrationsPatch
import app.revanced.patches.reddit.customclients.boostforreddit.misc.integrations.fingerprints.InitFingerprint
@Patch(requiresIntegrations = true)
object IntegrationsPatch : BaseIntegrationsPatch(
setOf(InitFingerprint)
)

View File

@@ -0,0 +1,10 @@
package app.revanced.patches.reddit.customclients.boostforreddit.misc.integrations.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patches.shared.misc.integrations.BaseIntegrationsPatch.IntegrationsFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
internal object InitFingerprint : IntegrationsFingerprint(
customFingerprint = { methodDef, _ -> methodDef.definingClass == "Lcom/rubenmayayo/reddit/MyApplication;" && methodDef.name == "onCreate" },
insertIndexResolver = { 1 } // Insert after call to super class.
)

View File

@@ -11,7 +11,7 @@ import app.revanced.patches.reddit.customclients.redditisfun.api.fingerprints.Ba
import app.revanced.patches.reddit.customclients.redditisfun.api.fingerprints.BuildAuthorizationStringFingerprint
import app.revanced.patches.reddit.customclients.redditisfun.api.fingerprints.GetUserAgentFingerprint
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction
import app.revanced.util.indexOfFirstInstructionOrThrow
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.StringReference
@Suppress("unused")
@@ -68,7 +68,7 @@ object SpoofClientPatch : BaseSpoofClientPatch(
// Reddit messed up and does not append a redirect uri to the authorization url to old.reddit.com/login.
// Replace old.reddit.com with ssl.reddit.com to fix this.
BuildAuthorizationStringFingerprint.result!!.mutableMethod.apply {
val index = indexOfFirstInstruction {
val index = indexOfFirstInstructionOrThrow {
getReference<StringReference>()?.contains("old.reddit.com") == true
}

View File

@@ -1,32 +1,49 @@
package app.revanced.patches.reddit.customclients.syncforreddit.fix.slink
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.fingerprint.MethodFingerprintResult
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.reddit.customclients.BaseFixSLinksPatch
import app.revanced.patches.reddit.customclients.syncforreddit.fix.slink.fingerprints.LinkHelperOpenLinkFingerprint
import app.revanced.util.exception
import app.revanced.patches.reddit.customclients.syncforreddit.fix.slink.fingerprints.SetAuthorizationHeaderFingerprint
import app.revanced.patches.reddit.customclients.syncforreddit.misc.integrations.IntegrationsPatch
@Patch(
name = "Fix /s/ links",
description = "Fixes the issue where /s/ links do not work.",
compatiblePackages = [
@Suppress("unused")
object FixSLinksPatch : BaseFixSLinksPatch(
handleNavigationFingerprint = LinkHelperOpenLinkFingerprint,
setAccessTokenFingerprint = SetAuthorizationHeaderFingerprint,
compatiblePackages = setOf(
CompatiblePackage("com.laurencedawson.reddit_sync"),
CompatiblePackage("com.laurencedawson.reddit_sync.pro"),
CompatiblePackage("com.laurencedawson.reddit_sync.dev")
],
requiresIntegrations = true
)
object FixSLinksPatch : BytecodePatch(
setOf(LinkHelperOpenLinkFingerprint)
CompatiblePackage("com.laurencedawson.reddit_sync.dev"),
),
dependencies = setOf(IntegrationsPatch::class),
) {
override fun execute(context: BytecodeContext) =
LinkHelperOpenLinkFingerprint.result?.mutableMethod?.addInstructions(
1,
"""
invoke-static { p3 }, Lapp/revanced/integrations/syncforreddit/FixSLinksPatch;->resolveSLink(Ljava/lang/String;)Ljava/lang/String;
move-result-object p3
"""
) ?: throw LinkHelperOpenLinkFingerprint.exception
override val integrationsClassDescriptor = "Lapp/revanced/integrations/syncforreddit/FixSLinksPatch;"
override fun MethodFingerprintResult.patchNavigationHandler(context: BytecodeContext) {
mutableMethod.apply {
val urlRegister = "p3"
val tempRegister = "v2"
addInstructionsWithLabels(
0,
"""
invoke-static { $urlRegister }, $integrationsClassDescriptor->$resolveSLinkMethod
move-result $tempRegister
if-eqz $tempRegister, :continue
return $tempRegister
""",
ExternalLabel("continue", getInstruction(0)),
)
}
}
override fun MethodFingerprintResult.patchSetAccessToken(context: BytecodeContext) = mutableMethod.addInstruction(
0,
"invoke-static { p0 }, $integrationsClassDescriptor->$setAccessTokenMethod",
)
}

View File

@@ -0,0 +1,9 @@
package app.revanced.patches.reddit.customclients.syncforreddit.fix.slink.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
internal object SetAuthorizationHeaderFingerprint : MethodFingerprint(
strings = listOf("Authorization", "bearer "),
returnType = "Ljava/util/HashMap;",
customFingerprint = { methodDef, _ -> methodDef.definingClass == "Lcom/laurencedawson/reddit_sync/singleton/a;" },
)

View File

@@ -0,0 +1,10 @@
package app.revanced.patches.reddit.customclients.syncforreddit.misc.integrations
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.misc.integrations.BaseIntegrationsPatch
import app.revanced.patches.reddit.customclients.syncforreddit.misc.integrations.fingerprints.InitFingerprint
@Patch(requiresIntegrations = true)
object IntegrationsPatch : BaseIntegrationsPatch(
setOf(InitFingerprint)
)

View File

@@ -0,0 +1,10 @@
package app.revanced.patches.reddit.customclients.syncforreddit.misc.integrations.fingerprints
import app.revanced.patches.shared.misc.integrations.BaseIntegrationsPatch.IntegrationsFingerprint
internal object InitFingerprint : IntegrationsFingerprint(
customFingerprint = { methodDef, classDef ->
methodDef.name == "onCreate" && classDef.type == "Lcom/laurencedawson/reddit_sync/RedditApplication;"
},
insertIndexResolver = { 1 }, // Insert after call to super class.
)

View File

@@ -1,6 +1,7 @@
package app.revanced.patches.shared.misc.mapping
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.ResourcePatch
import org.w3c.dom.Element
import java.util.*
@@ -51,9 +52,10 @@ object ResourceMappingPatch : ResourcePatch() {
threadPoolExecutor.also { it.shutdown() }.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS)
}
operator fun get(type: String, name: String) = resourceMappings.first {
it.type == type && it.name == name
}.id
operator fun get(type: String, name: String) =
resourceMappings.firstOrNull {
it.type == type && it.name == name
}?.id ?: throw PatchException("Could not find resource type: $type name: $name")
data class ResourceElement(val type: String, val name: String, val id: Long)
}

View File

@@ -11,7 +11,7 @@ import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.tiktok.interaction.cleardisplay.fingerprints.OnClearDisplayEventFingerprint
import app.revanced.patches.tiktok.interaction.cleardisplay.fingerprints.OnRenderFirstFrameFingerprint
import app.revanced.util.exception
import app.revanced.util.indexOfFirstInstruction
import app.revanced.util.indexOfFirstInstructionOrThrow
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction22c
@@ -34,7 +34,7 @@ object RememberClearDisplayPatch : BytecodePatch(
OnClearDisplayEventFingerprint.result?.mutableMethod?.let {
// region Hook the "Clear display" configuration save event to remember the state of clear display.
val isEnabledIndex = it.indexOfFirstInstruction { opcode == Opcode.IGET_BOOLEAN } + 1
val isEnabledIndex = it.indexOfFirstInstructionOrThrow { opcode == Opcode.IGET_BOOLEAN } + 1
val isEnabledRegister = it.getInstruction<Instruction22c>(isEnabledIndex - 1).registerA
it.addInstructions(

View File

@@ -18,7 +18,7 @@ import app.revanced.patches.tiktok.misc.integrations.IntegrationsPatch
import app.revanced.patches.tiktok.misc.settings.SettingsPatch
import app.revanced.patches.tiktok.misc.settings.fingerprints.SettingsStatusLoadFingerprint
import app.revanced.util.exception
import app.revanced.util.indexOfFirstInstruction
import app.revanced.util.indexOfFirstInstructionOrThrow
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
@@ -81,16 +81,16 @@ object DownloadsPatch : BytecodePatch(
},
// Change the download path patch.
DownloadPathParentFingerprint to {
val targetIndex = indexOfFirstInstruction { opcode == Opcode.INVOKE_STATIC }
val targetIndex = indexOfFirstInstructionOrThrow { opcode == Opcode.INVOKE_STATIC }
val downloadUriMethod = context
.toMethodWalker(this)
.nextMethod(targetIndex, true)
.getMethod() as MutableMethod
val firstIndex = downloadUriMethod.indexOfFirstInstruction {
val firstIndex = downloadUriMethod.indexOfFirstInstructionOrThrow {
opcode == Opcode.INVOKE_DIRECT && ((this as Instruction35c).reference as MethodReference).name == "<init>"
}
val secondIndex = downloadUriMethod.indexOfFirstInstruction {
val secondIndex = downloadUriMethod.indexOfFirstInstructionOrThrow {
opcode == Opcode.INVOKE_STATIC && ((this as Instruction35c).reference as MethodReference).returnType.contains(
"Uri"
)

View File

@@ -14,6 +14,7 @@ import app.revanced.patches.tiktok.interaction.speed.fingerprints.SetSpeedFinger
import app.revanced.util.exception
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction
import app.revanced.util.indexOfFirstInstructionOrThrow
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction11x
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
@@ -38,7 +39,7 @@ object PlaybackSpeedPatch : BytecodePatch(
SetSpeedFingerprint.result?.let { onVideoSwiped ->
// Remember the playback speed of the current video.
GetSpeedFingerprint.result?.mutableMethod?.apply {
val injectIndex = indexOfFirstInstruction { getReference<MethodReference>()?.returnType == "F" } + 2
val injectIndex = indexOfFirstInstructionOrThrow { getReference<MethodReference>()?.returnType == "F" } + 2
val register = getInstruction<Instruction11x>(injectIndex - 1).registerA
addInstruction(

View File

@@ -44,7 +44,12 @@ import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
"19.08.36",
"19.09.38",
"19.10.39",
"19.11.43"
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
],
),
],

View File

@@ -38,7 +38,12 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
"19.08.36",
"19.09.38",
"19.10.39",
"19.11.43"
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
]
)
]

View File

@@ -43,7 +43,12 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
"19.08.36",
"19.09.38",
"19.10.39",
"19.11.43"
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
]
)
]

View File

@@ -31,7 +31,12 @@ import app.revanced.patches.youtube.video.information.VideoInformationPatch
"19.08.36",
"19.09.38",
"19.10.39",
"19.11.43"
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
],
),
],

View File

@@ -40,7 +40,12 @@ import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
"19.08.36",
"19.09.38",
"19.10.39",
"19.11.43"
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
]
)
]

View File

@@ -37,7 +37,12 @@ import app.revanced.util.resultOrThrow
"19.08.36",
"19.09.38",
"19.10.39",
"19.11.43"
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
],
),
],

View File

@@ -40,7 +40,12 @@ import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
"19.08.36",
"19.09.38",
"19.10.39",
"19.11.43"
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
]
)
]

View File

@@ -42,7 +42,12 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
"19.08.36",
"19.09.38",
"19.10.39",
"19.11.43"
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
]
)
]

View File

@@ -38,7 +38,12 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
"19.08.36",
"19.09.38",
"19.10.39",
"19.11.43"
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
]
)
],

View File

@@ -44,10 +44,12 @@ import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
"19.08.36",
"19.09.38",
"19.10.39",
"19.11.43", // 19.12.x has an issue with opening YT using external links,
// and the app then crashes if double tap to skip forward/back is immediately used.
// The stack trace shows a call coming from integrations SwipeController,
// but it may be a bug in YT itself as other target versions do not have this issue.
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
],
),
],

View File

@@ -42,7 +42,12 @@ import app.revanced.util.exception
"19.08.36",
"19.09.38",
"19.10.39",
"19.11.43"
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
]
)
],

View File

@@ -41,7 +41,12 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
"19.08.36",
"19.09.38",
"19.10.39",
"19.11.43"
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
]
)
]

View File

@@ -13,11 +13,12 @@ import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.misc.settings.SettingsPatch
import app.revanced.patches.youtube.shared.fingerprints.LayoutConstructorFingerprint
import app.revanced.util.exception
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionOrThrow
import app.revanced.util.indexOfIdResourceOrThrow
import com.android.tools.smali.dexlib2.iface.instruction.Instruction
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.MethodReference
@Patch(
@@ -52,6 +53,11 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
"19.09.38",
"19.10.39",
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
],
),
],
@@ -60,6 +66,10 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
object HideAutoplayButtonPatch : BytecodePatch(
setOf(LayoutConstructorFingerprint),
) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/youtube/patches/HideAutoplayButtonPatch;"
override fun execute(context: BytecodeContext) {
AddResourcesPatch(this::class)
@@ -67,33 +77,27 @@ object HideAutoplayButtonPatch : BytecodePatch(
SwitchPreference("revanced_hide_autoplay_button"),
)
LayoutConstructorFingerprint.result?.mutableMethod?.apply {
val layoutGenMethodInstructions = implementation!!.instructions
LayoutConstructorFingerprint.resultOrThrow().mutableMethod.apply {
val constIndex = indexOfIdResourceOrThrow("autonav_toggle")
val constRegister = getInstruction<OneRegisterInstruction>(constIndex).registerA
// resolve the offsets of where to insert the branch instructions and ...
val insertIndex = indexOfIdResourceOrThrow("autonav_preview_stub")
// where to branch away
val branchIndex =
layoutGenMethodInstructions.subList(insertIndex + 1, layoutGenMethodInstructions.size - 1)
.indexOfFirst {
((it as? ReferenceInstruction)?.reference as? MethodReference)?.name == "addOnLayoutChangeListener"
} + 2
val jumpInstruction = layoutGenMethodInstructions[insertIndex + branchIndex] as Instruction
// can be clobbered because this register is overwritten after the injected code
val clobberRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
// Add a conditional branch around the code that inflates and adds the auto repeat button.
val gotoIndex = indexOfFirstInstructionOrThrow(constIndex) {
val parameterTypes = getReference<MethodReference>()?.parameterTypes
opcode == Opcode.INVOKE_VIRTUAL &&
parameterTypes?.size == 2 &&
parameterTypes.first() == "Landroid/view/ViewStub;"
} + 1
addInstructionsWithLabels(
insertIndex,
constIndex,
"""
invoke-static {}, Lapp/revanced/integrations/youtube/patches/HideAutoplayButtonPatch;->isButtonShown()Z
move-result v$clobberRegister
if-eqz v$clobberRegister, :hidden
invoke-static {}, $INTEGRATIONS_CLASS_DESCRIPTOR->hideAutoPlayButton()Z
move-result v$constRegister
if-nez v$constRegister, :hidden
""",
ExternalLabel("hidden", jumpInstruction),
ExternalLabel("hidden", getInstruction(gotoIndex)),
)
} ?: throw LayoutConstructorFingerprint.exception
}
}
}

View File

@@ -42,7 +42,12 @@ import com.android.tools.smali.dexlib2.Opcode
"19.08.36",
"19.09.38",
"19.10.39",
"19.11.43"
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
]
)
]

View File

@@ -19,7 +19,7 @@ import app.revanced.patches.youtube.misc.navigation.NavigationBarHookPatch
import app.revanced.patches.youtube.misc.settings.SettingsPatch
import app.revanced.util.exception
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction
import app.revanced.util.indexOfFirstInstructionOrThrow
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
@@ -56,6 +56,11 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
"19.09.38",
"19.10.39",
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
],
),
],
@@ -111,7 +116,7 @@ object NavigationButtonsPatch : BytecodePatch(
// Hide navigation button labels.
CreatePivotBarFingerprint.result?.mutableMethod?.apply {
val setTextIndex = indexOfFirstInstruction {
val setTextIndex = indexOfFirstInstructionOrThrow {
getReference<MethodReference>()?.name == "setText"
}

View File

@@ -46,7 +46,12 @@ import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction3rc
"19.08.36",
"19.09.38",
"19.10.39",
"19.11.43"
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
]
)
]

View File

@@ -40,7 +40,12 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
"19.08.36",
"19.09.38",
"19.10.39",
"19.11.43"
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
]
)
]

View File

@@ -40,7 +40,12 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
"19.08.36",
"19.09.38",
"19.10.39",
"19.11.43"
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
]
)
]

View File

@@ -40,7 +40,12 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
"19.08.36",
"19.09.38",
"19.10.39",
"19.11.43"
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
]
)
]

View File

@@ -43,7 +43,12 @@ import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction21c
"19.08.36",
"19.09.38",
"19.10.39",
"19.11.43"
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
]
)
]

View File

@@ -40,7 +40,12 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
"19.08.36",
"19.09.38",
"19.10.39",
"19.11.43"
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
]
)
]

View File

@@ -36,7 +36,12 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
"19.08.36",
"19.09.38",
"19.10.39",
"19.11.43"
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
]
)
]

View File

@@ -36,7 +36,12 @@ import app.revanced.util.exception
"19.08.36",
"19.09.38",
"19.10.39",
"19.11.43"
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
]
)
]

View File

@@ -23,7 +23,6 @@ import app.revanced.patches.youtube.misc.navigation.NavigationBarHookPatch
import app.revanced.patches.youtube.misc.settings.SettingsPatch
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.TwoRegisterInstruction
@@ -59,7 +58,12 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
"19.08.36",
"19.09.38",
"19.10.39",
"19.11.43"
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
],
),
],
@@ -164,20 +168,21 @@ object HideLayoutComponentsPatch : BytecodePatch(
// region Mix playlists
ParseElementFromBufferFingerprint.resultOrThrow().let { result ->
val consumeByteBufferIndex = result.scanResult.patternScanResult!!.startIndex
val startIndex = result.scanResult.patternScanResult!!.startIndex
result.mutableMethod.apply {
val conversionContextRegister =
getInstruction<TwoRegisterInstruction>(consumeByteBufferIndex - 2).registerA
val byteBufferRegister = getInstruction<FiveRegisterInstruction>(consumeByteBufferIndex).registerD
val freeRegister = "v0"
val byteArrayParameter = "p3"
val conversionContextRegister = getInstruction<TwoRegisterInstruction>(startIndex).registerA
val returnEmptyComponentInstruction = getInstructions().last { it.opcode == Opcode.INVOKE_STATIC }
addInstructionsWithLabels(
consumeByteBufferIndex,
startIndex + 1,
"""
invoke-static {v$conversionContextRegister, v$byteBufferRegister}, $LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR->filterMixPlaylists(Ljava/lang/Object;[B)Z
move-result v0 # Conveniently same register happens to be free.
if-nez v0, :return_empty_component
invoke-static { v$conversionContextRegister, $byteArrayParameter }, $LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR->filterMixPlaylists(Ljava/lang/Object;[B)Z
move-result $freeRegister
if-nez $freeRegister, :return_empty_component
const/4 $freeRegister, 0x0 # Restore register, required for 19.16
""",
ExternalLabel("return_empty_component", returnEmptyComponentInstruction),
)

View File

@@ -4,7 +4,11 @@ import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.Opcode
internal object ParseElementFromBufferFingerprint : MethodFingerprint(
parameters = listOf("L","L","[B", "L","L"),
opcodes = listOf(Opcode.INVOKE_INTERFACE, Opcode.MOVE_RESULT_OBJECT),
strings = listOf("Failed to parse Element")
parameters = listOf("L", "L", "[B", "L", "L"),
opcodes = listOf(
Opcode.IGET_OBJECT,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT_OBJECT
),
strings = listOf("Failed to parse Element") // String is a partial match.
)

View File

@@ -47,7 +47,12 @@ import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
"19.08.36",
"19.09.38",
"19.10.39",
"19.11.43"
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
]
)
]

View File

@@ -41,7 +41,12 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
"19.08.36",
"19.09.38",
"19.10.39",
"19.11.43"
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
]
)
]

View File

@@ -38,7 +38,12 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
"19.08.36",
"19.09.38",
"19.10.39",
"19.11.43"
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
]
)
]

View File

@@ -43,7 +43,12 @@ import app.revanced.patches.youtube.shared.fingerprints.SeekbarOnDrawFingerprint
"19.08.36",
"19.09.38",
"19.10.39",
"19.11.43"
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
]
)
]

View File

@@ -55,6 +55,11 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
"19.09.38",
"19.10.39",
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
],
),
],

View File

@@ -35,7 +35,12 @@ import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
"19.08.36",
"19.09.38",
"19.10.39",
"19.11.43"
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
]
)
]

View File

@@ -36,7 +36,12 @@ import app.revanced.util.exception
"19.08.36",
"19.09.38",
"19.10.39",
"19.11.43"
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
]
)
]

View File

@@ -0,0 +1,370 @@
package app.revanced.patches.youtube.layout.miniplayer
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.removeInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
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.proxy.mutableTypes.MutableMethod
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
import app.revanced.patches.all.misc.resources.AddResourcesPatch
import app.revanced.patches.shared.misc.settings.preference.InputType
import app.revanced.patches.shared.misc.settings.preference.ListPreference
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen.Sorting
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
import app.revanced.patches.shared.misc.settings.preference.TextPreference
import app.revanced.patches.youtube.layout.miniplayer.MiniplayerResourcePatch.modernMiniplayerClose
import app.revanced.patches.youtube.layout.miniplayer.MiniplayerResourcePatch.modernMiniplayerExpand
import app.revanced.patches.youtube.layout.miniplayer.MiniplayerResourcePatch.modernMiniplayerForwardButton
import app.revanced.patches.youtube.layout.miniplayer.MiniplayerResourcePatch.modernMiniplayerRewindButton
import app.revanced.patches.youtube.layout.miniplayer.MiniplayerResourcePatch.scrimOverlay
import app.revanced.patches.youtube.layout.miniplayer.MiniplayerResourcePatch.ytOutlinePictureInPictureWhite24
import app.revanced.patches.youtube.layout.miniplayer.MiniplayerResourcePatch.ytOutlineXWhite24
import app.revanced.patches.youtube.layout.miniplayer.fingerprints.MiniplayerDimensionsCalculatorParentFingerprint
import app.revanced.patches.youtube.layout.miniplayer.fingerprints.MiniplayerModernAddViewListenerFingerprint
import app.revanced.patches.youtube.layout.miniplayer.fingerprints.MiniplayerModernCloseButtonFingerprint
import app.revanced.patches.youtube.layout.miniplayer.fingerprints.MiniplayerModernConstructorFingerprint
import app.revanced.patches.youtube.layout.miniplayer.fingerprints.MiniplayerModernExpandButtonFingerprint
import app.revanced.patches.youtube.layout.miniplayer.fingerprints.MiniplayerModernExpandCloseDrawablesFingerprint
import app.revanced.patches.youtube.layout.miniplayer.fingerprints.MiniplayerModernForwardButtonFingerprint
import app.revanced.patches.youtube.layout.miniplayer.fingerprints.MiniplayerModernOverlayViewFingerprint
import app.revanced.patches.youtube.layout.miniplayer.fingerprints.MiniplayerModernRewindButtonFingerprint
import app.revanced.patches.youtube.layout.miniplayer.fingerprints.MiniplayerModernViewParentFingerprint
import app.revanced.patches.youtube.layout.miniplayer.fingerprints.MiniplayerOverrideFingerprint
import app.revanced.patches.youtube.layout.miniplayer.fingerprints.MiniplayerOverrideNoContextFingerprint
import app.revanced.patches.youtube.layout.miniplayer.fingerprints.MiniplayerResponseModelSizeCheckFingerprint
import app.revanced.patches.youtube.layout.miniplayer.fingerprints.YouTubePlayerOverlaysLayoutFingerprint
import app.revanced.patches.youtube.layout.miniplayer.fingerprints.YouTubePlayerOverlaysLayoutFingerprint.YOUTUBE_PLAYER_OVERLAYS_LAYOUT_CLASS_NAME
import app.revanced.patches.youtube.layout.tablet.fingerprints.GetFormFactorFingerprint
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.misc.settings.SettingsPatch
import app.revanced.util.findOpcodeIndicesReversed
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionOrThrow
import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow
import app.revanced.util.patch.LiteralValueFingerprint
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.builder.MutableMethodImplementation
import com.android.tools.smali.dexlib2.iface.Method
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.TypeReference
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
// YT uses "Miniplayer" without a space between 'mini' and 'player: https://support.google.com/youtube/answer/9162927.
@Patch(
name = "Miniplayer",
description = "Adds options to change the in app minimized player, " +
"and if patching target 19.16+ adds options to use modern miniplayers.",
dependencies = [
IntegrationsPatch::class,
SettingsPatch::class,
AddResourcesPatch::class,
MiniplayerResourcePatch::class
],
compatiblePackages = [
CompatiblePackage(
"com.google.android.youtube", [
"18.32.39",
"18.37.36",
"18.38.44",
"18.43.45",
"18.44.41",
"18.45.43",
"18.48.39",
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.36",
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.38",
"19.10.39",
"19.11.43",
"19.12.41",
"19.13.37",
// 19.14 is left out, as it has incomplete miniplayer code and missing some UI resources.
// It's simpler to not bother with supporting this single old version.
// 19.15 has a different code for handling sub title texts,
// and also probably not worth making changes just to support this single old version.
"19.16.39" // Earliest supported version with modern miniplayers.
]
)
]
)
@Suppress("unused")
object MiniplayerPatch : BytecodePatch(
setOf(GetFormFactorFingerprint,
MiniplayerDimensionsCalculatorParentFingerprint,
MiniplayerResponseModelSizeCheckFingerprint,
MiniplayerOverrideFingerprint,
MiniplayerModernConstructorFingerprint,
MiniplayerModernViewParentFingerprint,
YouTubePlayerOverlaysLayoutFingerprint
)
) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/MiniplayerPatch;"
override fun execute(context: BytecodeContext) {
AddResourcesPatch(this::class)
// Modern mini player is only present and functional in 19.15+.
// Resource is not present in older versions. Using it to determine, if patching an old version.
val isPatchingOldVersion = ytOutlinePictureInPictureWhite24 < 0
SettingsPatch.PreferenceScreen.PLAYER.addPreferences(
PreferenceScreen(
key = "revanced_miniplayer_screen",
sorting = Sorting.UNSORTED,
preferences =
if (isPatchingOldVersion) {
setOf(
ListPreference(
"revanced_miniplayer_type",
summaryKey = null,
entriesKey = "revanced_miniplayer_type_legacy_entries",
entryValuesKey = "revanced_miniplayer_type_legacy_entry_values"
)
)
} else {
setOf(
ListPreference(
"revanced_miniplayer_type",
summaryKey = null,
entriesKey = "revanced_miniplayer_type_19_15_entries",
entryValuesKey = "revanced_miniplayer_type_19_15_entry_values"
),
SwitchPreference("revanced_miniplayer_hide_expand_close"),
SwitchPreference("revanced_miniplayer_hide_subtext"),
SwitchPreference("revanced_miniplayer_hide_rewind_forward"),
TextPreference("revanced_miniplayer_opacity", inputType = InputType.NUMBER)
)
}
)
)
// region Enable tablet miniplayer.
MiniplayerOverrideNoContextFingerprint.resolve(
context,
MiniplayerDimensionsCalculatorParentFingerprint.resultOrThrow().classDef
)
MiniplayerOverrideNoContextFingerprint.resultOrThrow().mutableMethod.apply {
findReturnIndicesReversed().forEach { index -> insertLegacyTabletMiniplayerOverride(index) }
}
// endregion
// region Legacy tablet Miniplayer hooks.
MiniplayerOverrideFingerprint.resultOrThrow().let {
val appNameStringIndex = it.scanResult.stringsScanResult!!.matches.first().index + 2
it.mutableMethod.apply {
val walkerMethod = context.toMethodWalker(this)
.nextMethod(appNameStringIndex, true)
.getMethod() as MutableMethod
walkerMethod.apply {
findReturnIndicesReversed().forEach { index -> insertLegacyTabletMiniplayerOverride(index) }
}
}
}
MiniplayerResponseModelSizeCheckFingerprint.resultOrThrow().let {
it.mutableMethod.insertLegacyTabletMiniplayerOverride(it.scanResult.patternScanResult!!.endIndex)
}
if (isPatchingOldVersion) {
// Return here, as patch below is only intended for new versions of the app.
return
}
// endregion
// region Enable modern miniplayer.
MiniplayerModernConstructorFingerprint.resultOrThrow().mutableClass.methods.forEach {
it.apply {
if (AccessFlags.CONSTRUCTOR.isSet(accessFlags)) {
val iPutIndex = indexOfFirstInstructionOrThrow {
this.opcode == Opcode.IPUT && this.getReference<FieldReference>()?.type == "I"
}
insertModernMiniplayerTypeOverride(iPutIndex)
} else {
findReturnIndicesReversed().forEach { index -> insertModernMiniplayerOverride(index) }
}
}
}
// endregion
// region Fix 19.16 using mixed up drawables for tablet modern.
// YT fixed this mistake in 19.17.
// Fix this, by swapping the drawable resource values with each other.
MiniplayerModernExpandCloseDrawablesFingerprint.apply {
resolve(
context,
MiniplayerModernViewParentFingerprint.resultOrThrow().classDef
)
}.resultOrThrow().mutableMethod.apply {
listOf(
ytOutlinePictureInPictureWhite24 to ytOutlineXWhite24,
ytOutlineXWhite24 to ytOutlinePictureInPictureWhite24,
).forEach { (originalResource, replacementResource) ->
val imageResourceIndex = indexOfFirstWideLiteralInstructionValueOrThrow(originalResource)
val register = getInstruction<OneRegisterInstruction>(imageResourceIndex).registerA
replaceInstruction(imageResourceIndex, "const v$register, $replacementResource")
}
}
// endregion
// region Add hooks to hide tablet modern miniplayer buttons.
listOf(
Triple(MiniplayerModernExpandButtonFingerprint, modernMiniplayerExpand,"hideMiniplayerExpandClose"),
Triple(MiniplayerModernCloseButtonFingerprint, modernMiniplayerClose, "hideMiniplayerExpandClose"),
Triple(MiniplayerModernRewindButtonFingerprint, modernMiniplayerRewindButton, "hideMiniplayerRewindForward"),
Triple(MiniplayerModernForwardButtonFingerprint, modernMiniplayerForwardButton, "hideMiniplayerRewindForward"),
Triple(MiniplayerModernOverlayViewFingerprint, scrimOverlay, "adjustMiniplayerOpacity")
).forEach { (fingerprint, literalValue, methodName) ->
fingerprint.resolve(
context,
MiniplayerModernViewParentFingerprint.resultOrThrow().classDef
)
fingerprint.hookInflatedView(
literalValue,
"Landroid/widget/ImageView;",
"$INTEGRATIONS_CLASS_DESCRIPTOR->$methodName(Landroid/widget/ImageView;)V"
)
}
MiniplayerModernAddViewListenerFingerprint.apply {
resolve(
context,
MiniplayerModernViewParentFingerprint.resultOrThrow().classDef
)
}.resultOrThrow().mutableMethod.addInstruction(
0,
"invoke-static { p1 }, $INTEGRATIONS_CLASS_DESCRIPTOR->" +
"hideMiniplayerSubTexts(Landroid/view/View;)V"
)
// Modern 2 has a broken overlay subtitle view that is always present.
// Modern 2 uses the same overlay controls as the regular video player,
// and the overlay views are added at runtime.
// Add a hook to the overlay class, and pass the added views to integrations.
YouTubePlayerOverlaysLayoutFingerprint.resultOrThrow().mutableClass.methods.add(
ImmutableMethod(
YOUTUBE_PLAYER_OVERLAYS_LAYOUT_CLASS_NAME,
"addView",
listOf(
ImmutableMethodParameter("Landroid/view/View;", null, null),
ImmutableMethodParameter("I", null, null),
ImmutableMethodParameter("Landroid/view/ViewGroup\$LayoutParams;", null, null),
),
"V",
AccessFlags.PUBLIC.value,
null,
null,
MutableMethodImplementation(4),
).toMutable().apply {
addInstructions(
"""
invoke-super { p0, p1, p2, p3 }, Landroid/view/ViewGroup;->addView(Landroid/view/View;ILandroid/view/ViewGroup${'$'}LayoutParams;)V
invoke-static { p1 }, $INTEGRATIONS_CLASS_DESCRIPTOR->playerOverlayGroupCreated(Landroid/view/View;)V
return-void
""",
)
}
)
// endregion
}
private fun Method.findReturnIndicesReversed() = findOpcodeIndicesReversed(Opcode.RETURN)
/**
* Adds an override to force legacy tablet miniplayer to be used or not used.
*/
private fun MutableMethod.insertLegacyTabletMiniplayerOverride(index: Int) {
insertBooleanOverride(index, "getLegacyTabletMiniplayerOverride")
}
/**
* Adds an override to force modern miniplayer to be used or not used.
*/
private fun MutableMethod.insertModernMiniplayerOverride(index: Int) {
insertBooleanOverride(index, "getModernMiniplayerOverride")
}
private fun MutableMethod.insertBooleanOverride(index: Int, methodName: String) {
val register = getInstruction<OneRegisterInstruction>(index).registerA
addInstructions(
index,
"""
invoke-static {v$register}, $INTEGRATIONS_CLASS_DESCRIPTOR->$methodName(Z)Z
move-result v$register
"""
)
}
/**
* Adds an override to specify which modern miniplayer is used.
*/
private fun MutableMethod.insertModernMiniplayerTypeOverride(iPutIndex: Int) {
val targetInstruction = getInstruction<TwoRegisterInstruction>(iPutIndex)
val targetReference = (targetInstruction as ReferenceInstruction).reference
addInstructions(
iPutIndex + 1, """
invoke-static { v${targetInstruction.registerA} }, $INTEGRATIONS_CLASS_DESCRIPTOR->getModernMiniplayerOverrideType(I)I
move-result v${targetInstruction.registerA}
# Original instruction
iput v${targetInstruction.registerA}, v${targetInstruction.registerB}, $targetReference
"""
)
removeInstruction(iPutIndex)
}
private fun LiteralValueFingerprint.hookInflatedView(
literalValue: Long,
hookedClassType: String,
integrationsMethodName: String,
) {
resultOrThrow().mutableMethod.apply {
val imageViewIndex = indexOfFirstInstructionOrThrow(
indexOfFirstWideLiteralInstructionValueOrThrow(literalValue)
) {
opcode == Opcode.CHECK_CAST && getReference<TypeReference>()?.type == hookedClassType
}
val register = getInstruction<OneRegisterInstruction>(imageViewIndex).registerA
addInstruction(
imageViewIndex + 1,
"invoke-static { v$register }, $integrationsMethodName"
)
}
}
}

View File

@@ -0,0 +1,81 @@
package app.revanced.patches.youtube.layout.miniplayer
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.misc.mapping.ResourceMappingPatch
@Patch(dependencies = [ResourceMappingPatch::class])
internal object MiniplayerResourcePatch : ResourcePatch() {
var floatyBarButtonTopMargin = -1L
// Only available in 19.15 and upwards.
var ytOutlineXWhite24 = -1L
var ytOutlinePictureInPictureWhite24 = -1L
var scrimOverlay = -1L
var modernMiniplayerClose = -1L
var modernMiniplayerExpand = -1L
var modernMiniplayerRewindButton = -1L
var modernMiniplayerForwardButton = -1L
var playerOverlays = -1L
override fun execute(context: ResourceContext) {
floatyBarButtonTopMargin = ResourceMappingPatch[
"dimen",
"floaty_bar_button_top_margin"
]
try {
ytOutlinePictureInPictureWhite24 = ResourceMappingPatch[
"drawable",
"yt_outline_picture_in_picture_white_24"
]
} catch (exception: PatchException) {
// Ignore, and assume the app is 19.14 or earlier.
return
}
ytOutlineXWhite24 = ResourceMappingPatch[
"drawable",
"yt_outline_x_white_24"
]
scrimOverlay = ResourceMappingPatch[
"id",
"scrim_overlay"
]
modernMiniplayerClose = ResourceMappingPatch[
"id",
"modern_miniplayer_close"
]
modernMiniplayerExpand = ResourceMappingPatch[
"id",
"modern_miniplayer_expand"
]
modernMiniplayerRewindButton = ResourceMappingPatch[
"id",
"modern_miniplayer_rewind_button"
]
modernMiniplayerForwardButton = ResourceMappingPatch[
"id",
"modern_miniplayer_forward_button"
]
playerOverlays = ResourceMappingPatch[
"layout",
"player_overlays"
]
// Resource id is not used during patching, but is used by integrations.
// Verify the resource is present while patching.
ResourceMappingPatch[
"id",
"modern_miniplayer_subtitle_text"
]
}
}

View File

@@ -0,0 +1,13 @@
package app.revanced.patches.youtube.layout.miniplayer.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patches.youtube.layout.miniplayer.MiniplayerResourcePatch
import app.revanced.util.patch.LiteralValueFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
internal object MiniplayerDimensionsCalculatorParentFingerprint : LiteralValueFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
returnType = "V",
parameters = listOf("L"),
literalSupplier = { MiniplayerResourcePatch.floatyBarButtonTopMargin }
)

View File

@@ -0,0 +1,14 @@
package app.revanced.patches.youtube.layout.miniplayer.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
/**
* Resolves using the class found in [MiniplayerModernViewParentFingerprint].
*/
internal object MiniplayerModernAddViewListenerFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
returnType = "V",
parameters = listOf("Landroid/view/View;")
)

View File

@@ -0,0 +1,16 @@
package app.revanced.patches.youtube.layout.miniplayer.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patches.youtube.layout.miniplayer.MiniplayerResourcePatch
import app.revanced.util.patch.LiteralValueFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
/**
* Resolves using the class found in [MiniplayerModernViewParentFingerprint].
*/
internal object MiniplayerModernCloseButtonFingerprint : LiteralValueFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
returnType = "Landroid/widget/ImageView;",
parameters = listOf(),
literalSupplier = { MiniplayerResourcePatch.modernMiniplayerClose }
)

View File

@@ -0,0 +1,11 @@
package app.revanced.patches.youtube.layout.miniplayer.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.util.patch.LiteralValueFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
internal object MiniplayerModernConstructorFingerprint : LiteralValueFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
parameters = listOf("L"),
literalSupplier = { 45623000L } // Magic number found in the constructor.
)

View File

@@ -0,0 +1,16 @@
package app.revanced.patches.youtube.layout.miniplayer.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patches.youtube.layout.miniplayer.MiniplayerResourcePatch
import app.revanced.util.patch.LiteralValueFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
/**
* Resolves using the class found in [MiniplayerModernViewParentFingerprint].
*/
internal object MiniplayerModernExpandButtonFingerprint : LiteralValueFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
returnType = "Landroid/widget/ImageView;",
parameters = listOf(),
literalSupplier = { MiniplayerResourcePatch.modernMiniplayerExpand }
)

View File

@@ -0,0 +1,16 @@
package app.revanced.patches.youtube.layout.miniplayer.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patches.youtube.layout.miniplayer.MiniplayerResourcePatch
import app.revanced.util.patch.LiteralValueFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
/**
* Resolves using the class found in [MiniplayerModernViewParentFingerprint].
*/
internal object MiniplayerModernExpandCloseDrawablesFingerprint : LiteralValueFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
returnType = "V",
parameters = listOf("L"),
literalSupplier = { MiniplayerResourcePatch.ytOutlinePictureInPictureWhite24 }
)

View File

@@ -0,0 +1,16 @@
package app.revanced.patches.youtube.layout.miniplayer.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patches.youtube.layout.miniplayer.MiniplayerResourcePatch
import app.revanced.util.patch.LiteralValueFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
/**
* Resolves using the class found in [MiniplayerModernViewParentFingerprint].
*/
internal object MiniplayerModernForwardButtonFingerprint : LiteralValueFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
returnType = "Landroid/widget/ImageView;",
parameters = listOf(),
literalSupplier = { MiniplayerResourcePatch.modernMiniplayerForwardButton }
)

View File

@@ -0,0 +1,16 @@
package app.revanced.patches.youtube.layout.miniplayer.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patches.youtube.layout.miniplayer.MiniplayerResourcePatch
import app.revanced.util.patch.LiteralValueFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
/**
* Resolves using the class found in [MiniplayerModernViewParentFingerprint].
*/
internal object MiniplayerModernOverlayViewFingerprint : LiteralValueFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
returnType = "V",
parameters = listOf(),
literalSupplier = { MiniplayerResourcePatch.scrimOverlay }
)

View File

@@ -0,0 +1,16 @@
package app.revanced.patches.youtube.layout.miniplayer.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patches.youtube.layout.miniplayer.MiniplayerResourcePatch
import app.revanced.util.patch.LiteralValueFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
/**
* Resolves using the class found in [MiniplayerModernViewParentFingerprint].
*/
internal object MiniplayerModernRewindButtonFingerprint : LiteralValueFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
returnType = "Landroid/widget/ImageView;",
parameters = listOf(),
literalSupplier = { MiniplayerResourcePatch.modernMiniplayerRewindButton }
)

View File

@@ -0,0 +1,12 @@
package app.revanced.patches.youtube.layout.miniplayer.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
internal object MiniplayerModernViewParentFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
returnType = "Ljava/lang/String;",
parameters = listOf(),
strings = listOf("player_overlay_modern_mini_player_controls")
)

View File

@@ -1,10 +1,10 @@
package app.revanced.patches.youtube.layout.tabletminiplayer.fingerprints
package app.revanced.patches.youtube.layout.miniplayer.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
internal object MiniPlayerOverrideFingerprint : MethodFingerprint(
internal object MiniplayerOverrideFingerprint : MethodFingerprint(
returnType = "L",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf("L"),

View File

@@ -0,0 +1,12 @@
package app.revanced.patches.youtube.layout.miniplayer.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 MiniplayerOverrideNoContextFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL,
returnType = "Z",
opcodes = listOf(Opcode.IGET_BOOLEAN), // anchor to insert the instruction
)

View File

@@ -1,15 +1,15 @@
package app.revanced.patches.youtube.layout.tabletminiplayer.fingerprints
package app.revanced.patches.youtube.layout.miniplayer.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 MiniPlayerResponseModelSizeCheckFingerprint : MethodFingerprint(
"L",
AccessFlags.PUBLIC or AccessFlags.FINAL,
listOf("Ljava/lang/Object;", "Ljava/lang/Object;"),
listOf(
internal object MiniplayerResponseModelSizeCheckFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
returnType = "L",
parameters = listOf("Ljava/lang/Object;", "Ljava/lang/Object;"),
opcodes = listOf(
Opcode.RETURN_OBJECT,
Opcode.CHECK_CAST,
Opcode.CHECK_CAST,

View File

@@ -0,0 +1,13 @@
package app.revanced.patches.youtube.layout.miniplayer.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
import app.revanced.patches.youtube.layout.miniplayer.fingerprints.YouTubePlayerOverlaysLayoutFingerprint.YOUTUBE_PLAYER_OVERLAYS_LAYOUT_CLASS_NAME
internal object YouTubePlayerOverlaysLayoutFingerprint : MethodFingerprint(
customFingerprint = { _, classDef ->
classDef.type == YOUTUBE_PLAYER_OVERLAYS_LAYOUT_CLASS_NAME
}
) {
const val YOUTUBE_PLAYER_OVERLAYS_LAYOUT_CLASS_NAME =
"Lcom/google/android/apps/youtube/app/common/player/overlay/YouTubePlayerOverlaysLayout;"
}

View File

@@ -37,7 +37,12 @@ import app.revanced.util.exception
"19.08.36",
"19.09.38",
"19.10.39",
"19.11.43"
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
]
)
]

View File

@@ -32,7 +32,12 @@ import org.w3c.dom.Element
"19.08.36",
"19.09.38",
"19.10.39",
"19.11.43"
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
],
),
],

View File

@@ -1,7 +1,5 @@
package app.revanced.patches.youtube.layout.player.overlay
import app.revanced.util.exception
import app.revanced.util.indexOfFirstWideLiteralInstructionValue
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
@@ -9,6 +7,8 @@ import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.youtube.layout.player.overlay.fingerprints.CreatePlayerOverviewFingerprint
import app.revanced.util.exception
import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Patch(
@@ -27,7 +27,7 @@ object CustomPlayerOverlayOpacityPatch : BytecodePatch(setOf(CreatePlayerOvervie
CreatePlayerOverviewFingerprint.result?.let { result ->
result.mutableMethod.apply {
val viewRegisterIndex =
indexOfFirstWideLiteralInstructionValue(CustomPlayerOverlayOpacityResourcePatch.scrimOverlayId) + 3
indexOfFirstWideLiteralInstructionValueOrThrow(CustomPlayerOverlayOpacityResourcePatch.scrimOverlayId) + 3
val viewRegister =
getInstruction<OneRegisterInstruction>(viewRegisterIndex).registerA

View File

@@ -31,7 +31,7 @@ import app.revanced.patches.youtube.shared.fingerprints.RollingNumberTextViewAni
import app.revanced.patches.youtube.video.videoid.VideoIdPatch
import app.revanced.util.exception
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction
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
@@ -66,7 +66,12 @@ import com.android.tools.smali.dexlib2.iface.reference.TypeReference
"19.08.36",
"19.09.38",
"19.10.39",
"19.11.43"
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
]
)
]
@@ -142,11 +147,10 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
TextComponentLookupFingerprint.resultOrThrow().mutableMethod.apply {
// Find the instruction for creating the text data object.
val textDataClassType = TextComponentDataFingerprint.resultOrThrow().classDef.type
val insertIndex = indexOfFirstInstruction {
val insertIndex = indexOfFirstInstructionOrThrow {
opcode == Opcode.NEW_INSTANCE &&
getReference<TypeReference>()?.type == textDataClassType
}
if (insertIndex < 0) throw PatchException("Could not find data creation instruction")
val tempRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
// Find the instruction that sets the span to an instance field.
@@ -335,7 +339,7 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
realTimeUpdateTextViewMethod
).forEach { insertMethod ->
insertMethod.apply {
val setTextIndex = indexOfFirstInstruction {
val setTextIndex = indexOfFirstInstructionOrThrow {
getReference<MethodReference>()?.name == "setText"
}

View File

@@ -41,7 +41,12 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
"19.08.36",
"19.09.38",
"19.10.39",
"19.11.43"
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
]
)
]

View File

@@ -37,7 +37,12 @@ import app.revanced.util.exception
"19.08.36",
"19.09.38",
"19.10.39",
"19.11.43"
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
]
)
]

View File

@@ -1,7 +1,5 @@
package app.revanced.patches.youtube.layout.seekbar
import app.revanced.util.exception
import app.revanced.util.indexOfFirstWideLiteralInstructionValue
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
@@ -15,6 +13,8 @@ import app.revanced.patches.youtube.layout.seekbar.fingerprints.ShortsSeekbarCol
import app.revanced.patches.youtube.layout.theme.LithoColorHookPatch
import app.revanced.patches.youtube.layout.theme.LithoColorHookPatch.lithoColorOverrideHook
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.util.exception
import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
@@ -30,7 +30,7 @@ internal object SeekbarColorBytecodePatch : BytecodePatch(
override fun execute(context: BytecodeContext) {
fun MutableMethod.addColorChangeInstructions(resourceId: Long) {
val registerIndex = indexOfFirstWideLiteralInstructionValue(resourceId) + 2
val registerIndex = indexOfFirstWideLiteralInstructionValueOrThrow(resourceId) + 2
val colorRegister = getInstruction<OneRegisterInstruction>(registerIndex).registerA
addInstructions(
registerIndex + 1,

View File

@@ -52,6 +52,11 @@ import com.android.tools.smali.dexlib2.iface.reference.StringReference
"19.09.38",
"19.10.39",
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
],
),
],

View File

@@ -40,7 +40,12 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
"19.08.36",
"19.09.38",
"19.10.39",
"19.11.43"
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
]
)
]

View File

@@ -5,7 +5,6 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWith
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.all.misc.resources.AddResourcesPatch
@@ -15,7 +14,7 @@ import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.misc.settings.SettingsPatch
import app.revanced.util.exception
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction
import app.revanced.util.indexOfFirstInstructionOrThrow
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
@@ -46,7 +45,12 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
"19.08.36",
"19.09.38",
"19.10.39",
"19.11.43"
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
]
)
]
@@ -67,12 +71,11 @@ object DisableResumingShortsOnStartupPatch : BytecodePatch(
)
UserWasInShortsFingerprint.result?.mutableMethod?.apply {
val listenableInstructionIndex = indexOfFirstInstruction {
val listenableInstructionIndex = indexOfFirstInstructionOrThrow {
opcode == Opcode.INVOKE_INTERFACE &&
getReference<MethodReference>()?.definingClass == "Lcom/google/common/util/concurrent/ListenableFuture;" &&
getReference<MethodReference>()?.name == "isDone"
}
if (listenableInstructionIndex < 0) throw PatchException("Could not find instruction index")
val originalInstructionRegister = getInstruction<FiveRegisterInstruction>(listenableInstructionIndex).registerC
val freeRegister = getInstruction<OneRegisterInstruction>(listenableInstructionIndex + 1).registerA

View File

@@ -13,18 +13,51 @@ import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
import app.revanced.patches.youtube.layout.tablet.fingerprints.GetFormFactorFingerprint
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.misc.settings.SettingsPatch
import app.revanced.util.exception
import app.revanced.util.resultOrThrow
@Patch(
name = "Enable tablet layout",
description = "Adds an option to spoof the device form factor to a tablet which enables the tablet layout.",
dependencies = [IntegrationsPatch::class, SettingsPatch::class, AddResourcesPatch::class],
compatiblePackages = [CompatiblePackage("com.google.android.youtube")]
description = "Adds an option to enable tablet layout",
dependencies = [
IntegrationsPatch::class,
SettingsPatch::class,
AddResourcesPatch::class,
],
compatiblePackages = [
CompatiblePackage(
"com.google.android.youtube", arrayOf(
"18.32.39",
"18.37.36",
"18.38.44",
"18.43.45",
"18.44.41",
"18.45.43",
"18.48.39",
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.36",
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.38",
"19.10.39",
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39"
)
)
]
)
@Suppress("unused")
object EnableTabletLayoutPatch : BytecodePatch(
setOf(GetFormFactorFingerprint)
) {
object EnableTabletLayoutPatch : BytecodePatch(setOf(GetFormFactorFingerprint)) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/TabletLayoutPatch;"
override fun execute(context: BytecodeContext) {
AddResourcesPatch(this::class)
@@ -32,7 +65,7 @@ object EnableTabletLayoutPatch : BytecodePatch(
SwitchPreference("revanced_tablet_layout")
)
GetFormFactorFingerprint.result?.let {
GetFormFactorFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val returnIsLargeFormFactorIndex = getInstructions().lastIndex - 4
val returnIsLargeFormFactorLabel = getInstruction(returnIsLargeFormFactorIndex)
@@ -40,8 +73,8 @@ object EnableTabletLayoutPatch : BytecodePatch(
addInstructionsWithLabels(
0,
"""
invoke-static { }, Lapp/revanced/integrations/youtube/patches/EnableTabletLayoutPatch;->enableTabletLayout()Z
move-result v0 # Free register
invoke-static { }, $INTEGRATIONS_CLASS_DESCRIPTOR->getTabletLayoutEnabled()Z
move-result v0
if-nez v0, :is_large_form_factor
""",
ExternalLabel(
@@ -50,6 +83,6 @@ object EnableTabletLayoutPatch : BytecodePatch(
)
)
}
} ?: GetFormFactorFingerprint.exception
}
}
}

View File

@@ -21,5 +21,6 @@ internal object GetFormFactorFingerprint : MethodFingerprint(
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.RETURN_OBJECT
)
),
strings = listOf("")
)

View File

@@ -1,147 +1,11 @@
package app.revanced.patches.youtube.layout.tabletminiplayer
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.fingerprint.MethodFingerprint
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.all.misc.resources.AddResourcesPatch
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
import app.revanced.patches.youtube.layout.tabletminiplayer.fingerprints.MiniPlayerDimensionsCalculatorParentFingerprint
import app.revanced.patches.youtube.layout.tabletminiplayer.fingerprints.MiniPlayerOverrideFingerprint
import app.revanced.patches.youtube.layout.tabletminiplayer.fingerprints.MiniPlayerOverrideNoContextFingerprint
import app.revanced.patches.youtube.layout.tabletminiplayer.fingerprints.MiniPlayerResponseModelSizeCheckFingerprint
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.misc.settings.SettingsPatch
import app.revanced.util.exception
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import app.revanced.patches.youtube.layout.miniplayer.MiniplayerPatch
@Patch(
name = "Tablet mini player",
description = "Adds an option to enable the tablet mini player layout.",
dependencies = [IntegrationsPatch::class, SettingsPatch::class, AddResourcesPatch::class],
compatiblePackages = [
CompatiblePackage(
"com.google.android.youtube", arrayOf(
"18.32.39",
"18.37.36",
"18.38.44",
"18.43.45",
"18.44.41",
"18.45.43",
"18.48.39",
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.36",
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.38",
"19.10.39",
"19.11.43"
)
)
]
)
@Suppress("unused")
object TabletMiniPlayerPatch : BytecodePatch(
setOf(
MiniPlayerDimensionsCalculatorParentFingerprint,
MiniPlayerResponseModelSizeCheckFingerprint,
MiniPlayerOverrideFingerprint
)
) {
@Deprecated("This patch class has been renamed to Miniplayer.")
object TabletMiniPlayerPatch : BytecodePatch(dependencies = setOf(MiniplayerPatch::class)) {
override fun execute(context: BytecodeContext) {
AddResourcesPatch(this::class)
SettingsPatch.PreferenceScreen.GENERAL_LAYOUT.addPreferences(
SwitchPreference("revanced_tablet_miniplayer")
)
// First resolve the fingerprints via the parent fingerprint.
MiniPlayerDimensionsCalculatorParentFingerprint.result
?: throw MiniPlayerDimensionsCalculatorParentFingerprint.exception
val miniPlayerClass = MiniPlayerDimensionsCalculatorParentFingerprint.result!!.classDef
/*
* No context parameter method.
*/
MiniPlayerOverrideNoContextFingerprint.resolve(context, miniPlayerClass)
val (method, _, parameterRegister) = MiniPlayerOverrideNoContextFingerprint.addProxyCall()
// Insert right before the return instruction.
val secondInsertIndex = method.implementation!!.instructions.size - 1
method.insertOverride(
secondInsertIndex, parameterRegister
/** same register used to return **/
)
/*
* Override every return instruction with the proxy call.
*/
MiniPlayerOverrideFingerprint.result?.let { result ->
result.mutableMethod.let { method ->
val appNameStringIndex = result.scanResult.stringsScanResult!!.matches.first().index + 2
context.toMethodWalker(method).nextMethod(appNameStringIndex, true)
.getMethod() as MutableMethod
}.apply {
implementation!!.let { implementation ->
val returnIndices = implementation.instructions
.withIndex()
.filter { (_, instruction) -> instruction.opcode == Opcode.RETURN }
.map { (index, _) -> index }
if (returnIndices.isEmpty()) throw PatchException("No return instructions found.")
// This method clobbers register p0 to return the value, calculate to override.
val returnedRegister = implementation.registerCount - parameters.size
// Hook the returned register on every return instruction.
returnIndices.forEach { index -> insertOverride(index, returnedRegister) }
}
}
return@let
} ?: throw MiniPlayerOverrideFingerprint.exception
/*
* Size check return value override.
*/
MiniPlayerResponseModelSizeCheckFingerprint.addProxyCall()
}
// Helper methods.
private fun MethodFingerprint.addProxyCall(): Triple<MutableMethod, Int, Int> {
val (method, scanIndex, parameterRegister) = this.unwrap()
method.insertOverride(scanIndex, parameterRegister)
return Triple(method, scanIndex, parameterRegister)
}
private fun MutableMethod.insertOverride(index: Int, overrideRegister: Int) {
this.addInstructions(
index,
"""
invoke-static {v$overrideRegister}, Lapp/revanced/integrations/youtube/patches/TabletMiniPlayerOverridePatch;->getTabletMiniPlayerOverride(Z)Z
move-result v$overrideRegister
"""
)
}
private fun MethodFingerprint.unwrap(): Triple<MutableMethod, Int, Int> {
val result = this.result!!
val scanIndex = result.scanResult.patternScanResult!!.endIndex
val method = result.mutableMethod
val instructions = method.implementation!!.instructions
val parameterRegister = (instructions[scanIndex] as OneRegisterInstruction).registerA
return Triple(method, scanIndex, parameterRegister)
}
}

View File

@@ -1,23 +0,0 @@
package app.revanced.patches.youtube.layout.tabletminiplayer.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 MiniPlayerDimensionsCalculatorParentFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
returnType = "V",
parameters = listOf("F"),
opcodes = listOf(
Opcode.CONST_HIGH16,
Opcode.ADD_FLOAT_2ADDR,
null, // Opcode.MUL_FLOAT or Opcode.MUL_FLOAT_2ADDR
Opcode.CONST_4,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT,
Opcode.FLOAT_TO_INT,
Opcode.INVOKE_INTERFACE,
Opcode.RETURN_VOID,
)
)

View File

@@ -1,11 +0,0 @@
package app.revanced.patches.youtube.layout.tabletminiplayer.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 MiniPlayerOverrideNoContextFingerprint : MethodFingerprint(
"Z", AccessFlags.FINAL or AccessFlags.PRIVATE,
opcodes = listOf(Opcode.RETURN), // anchor to insert the instruction
)

View File

@@ -16,7 +16,7 @@ import app.revanced.patches.youtube.layout.theme.fingerprints.UseGradientLoading
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.misc.settings.SettingsPatch
import app.revanced.util.exception
import app.revanced.util.indexOfFirstWideLiteralInstructionValue
import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow
import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@@ -52,7 +52,12 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
"19.08.36",
"19.09.38",
"19.10.39",
"19.11.43"
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
]
)
]
@@ -118,7 +123,7 @@ object ThemeBytecodePatch : BytecodePatch(
)
UseGradientLoadingScreenFingerprint.result?.mutableMethod?.apply {
val isEnabledIndex = indexOfFirstWideLiteralInstructionValue(GRADIENT_LOADING_SCREEN_AB_CONSTANT) + 3
val isEnabledIndex = indexOfFirstWideLiteralInstructionValueOrThrow(GRADIENT_LOADING_SCREEN_AB_CONSTANT) + 3
val isEnabledRegister = getInstruction<OneRegisterInstruction>(isEnabledIndex - 1).registerA
addInstructions(

View File

@@ -63,7 +63,12 @@ import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
"19.08.36",
"19.09.38",
"19.10.39",
"19.11.43"
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
],
),
],

View File

@@ -41,7 +41,12 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
"19.08.36",
"19.09.38",
"19.10.39",
"19.11.43"
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
]
)
]

View File

@@ -0,0 +1,112 @@
package app.revanced.patches.youtube.misc.backgroundplayback
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.all.misc.resources.AddResourcesPatch
import app.revanced.patches.shared.misc.settings.preference.NonInteractivePreference
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.misc.backgroundplayback.fingerprints.KidsBackgroundPlaybackPolicyControllerFingerprint
import app.revanced.patches.youtube.misc.backgroundplayback.fingerprints.BackgroundPlaybackManagerFingerprint
import app.revanced.patches.youtube.misc.backgroundplayback.fingerprints.BackgroundPlaybackSettingsFingerprint
import app.revanced.patches.youtube.misc.playertype.PlayerTypeHookPatch
import app.revanced.patches.youtube.misc.settings.SettingsPatch
import app.revanced.patches.youtube.video.information.VideoInformationPatch
import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
@Patch(
name = "Remove background playback restrictions",
description = "Removes restrictions on background playback, including playing kids videos in the background.",
dependencies = [
BackgroundPlaybackResourcePatch::class,
IntegrationsPatch::class,
PlayerTypeHookPatch::class,
VideoInformationPatch::class,
SettingsPatch::class,
AddResourcesPatch::class
],
compatiblePackages = [
CompatiblePackage(
"com.google.android.youtube",
[
"18.48.39",
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.36",
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.38",
"19.10.39",
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
]
)
]
)
@Suppress("unused")
object BackgroundPlaybackPatch : BytecodePatch(
setOf(
BackgroundPlaybackManagerFingerprint,
BackgroundPlaybackSettingsFingerprint,
KidsBackgroundPlaybackPolicyControllerFingerprint
)
) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/youtube/patches/BackgroundPlaybackPatch;"
override fun execute(context: BytecodeContext) {
AddResourcesPatch(this::class)
SettingsPatch.PreferenceScreen.MISC.addPreferences(
NonInteractivePreference("revanced_background_playback")
)
BackgroundPlaybackManagerFingerprint.resultOrThrow().mutableMethod.addInstructions(
0,
"""
invoke-static {}, $INTEGRATIONS_CLASS_DESCRIPTOR->playbackIsNotShort()Z
move-result v0
return v0
"""
)
// Enable background playback option in YouTube settings
BackgroundPlaybackSettingsFingerprint.resultOrThrow().mutableMethod.apply {
val booleanCalls = implementation!!.instructions.withIndex()
.filter { ((it.value as? ReferenceInstruction)?.reference as? MethodReference)?.returnType == "Z" }
val settingsBooleanIndex = booleanCalls.elementAt(1).index
val settingsBooleanMethod =
context.toMethodWalker(this).nextMethod(settingsBooleanIndex, true).getMethod() as MutableMethod
settingsBooleanMethod.addInstructions(
0,
"""
invoke-static {}, $INTEGRATIONS_CLASS_DESCRIPTOR->overrideBackgroundPlaybackAvailable()Z
move-result v0
return v0
"""
)
}
// Force allowing background play for videos labeled for kids.
KidsBackgroundPlaybackPolicyControllerFingerprint.resultOrThrow().mutableMethod.addInstruction(
0,
"return-void"
)
}
}

View File

@@ -0,0 +1,17 @@
package app.revanced.patches.youtube.misc.backgroundplayback
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.misc.mapping.ResourceMappingPatch
@Patch(
dependencies = [ResourceMappingPatch::class],
)
internal object BackgroundPlaybackResourcePatch : ResourcePatch() {
internal var prefBackgroundAndOfflineCategoryId: Long = -1
override fun execute(context: ResourceContext) {
prefBackgroundAndOfflineCategoryId = ResourceMappingPatch["string", "pref_background_and_offline_category"]
}
}

View File

@@ -1,11 +1,11 @@
package app.revanced.patches.youtube.misc.minimizedplayback.fingerprints
package app.revanced.patches.youtube.misc.backgroundplayback.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 MinimizedPlaybackManagerFingerprint : MethodFingerprint(
internal object BackgroundPlaybackManagerFingerprint : MethodFingerprint(
"Z",
AccessFlags.PUBLIC or AccessFlags.STATIC,
listOf("L"),

View File

@@ -1,11 +1,12 @@
package app.revanced.patches.youtube.misc.minimizedplayback.fingerprints
package app.revanced.patches.youtube.misc.backgroundplayback.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import app.revanced.patches.youtube.misc.backgroundplayback.BackgroundPlaybackResourcePatch
import app.revanced.util.patch.LiteralValueFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
internal object MinimizedPlaybackSettingsFingerprint : MethodFingerprint(
internal object BackgroundPlaybackSettingsFingerprint : LiteralValueFingerprint(
returnType = "Ljava/lang/String;",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf(),
@@ -16,8 +17,7 @@ internal object MinimizedPlaybackSettingsFingerprint : MethodFingerprint(
Opcode.MOVE_RESULT,
Opcode.IF_EQZ,
Opcode.IF_NEZ,
Opcode.GOTO,
Opcode.IGET_OBJECT,
Opcode.CHECK_CAST
Opcode.GOTO
),
literalSupplier = { BackgroundPlaybackResourcePatch.prefBackgroundAndOfflineCategoryId }
)

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