Compare commits

...

12 Commits

Author SHA1 Message Date
semantic-release-bot
c40911a815 chore(release): 4.5.1-dev.1 [skip ci]
## [4.5.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.5.0...v4.5.1-dev.1) (2024-03-30)

### Bug Fixes

* **Tumblr:** Restore compatibility with latest versions ([#2955](https://github.com/ReVanced/revanced-patches/issues/2955)) ([1a53a93](1a53a93cd2))
2024-03-30 22:10:49 +00:00
Temm
1a53a93cd2 fix(Tumblr): Restore compatibility with latest versions (#2955) 2024-03-30 23:08:34 +01:00
semantic-release-bot
2e68c65c9f chore(release): 4.5.0 [skip ci]
# [4.5.0](https://github.com/ReVanced/revanced-patches/compare/v4.4.0...v4.5.0) (2024-03-30)

### Features

* **YouTube - Alternative thumbnails:** Selectively enable for home / subscription / search ([#2926](https://github.com/ReVanced/revanced-patches/issues/2926)) ([a272962](a27296223f))
* **YouTube - GmsCore:** Require ignoring battery optimizations ([#2952](https://github.com/ReVanced/revanced-patches/issues/2952)) ([9b3c060](9b3c060acb))
2024-03-30 19:42:19 +00:00
oSumAtrIX
6f8d92827b chore: Merge branch dev to main (#2943) 2024-03-30 20:40:10 +01:00
semantic-release-bot
ab2260acfd chore(release): 4.5.0-dev.2 [skip ci]
# [4.5.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.5.0-dev.1...v4.5.0-dev.2) (2024-03-30)

### Features

* **YouTube - GmsCore:** Require ignoring battery optimizations ([#2952](https://github.com/ReVanced/revanced-patches/issues/2952)) ([9b3c060](9b3c060acb))
2024-03-30 18:54:26 +00:00
oSumAtrIX
9b3c060acb feat(YouTube - GmsCore): Require ignoring battery optimizations (#2952) 2024-03-30 19:52:22 +01:00
LisoUseInAIKyrios
bbc4a6bfa0 chore: fix typo 2024-03-30 20:33:28 +04:00
Ushie
4df9b9d5b1 ci: Add workflow to sync Crowdin translations (#2953) 2024-03-30 03:15:07 +01:00
semantic-release-bot
eebf72f476 chore(release): 4.5.0-dev.1 [skip ci]
# [4.5.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.4.0...v4.5.0-dev.1) (2024-03-29)

### Features

* **YouTube - Alternative thumbnails:** Selectively enable for home / subscription / search ([#2926](https://github.com/ReVanced/revanced-patches/issues/2926)) ([a272962](a27296223f))
2024-03-29 09:31:55 +00:00
LisoUseInAIKyrios
a27296223f feat(YouTube - Alternative thumbnails): Selectively enable for home / subscription / search (#2926)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2024-03-29 13:30:00 +04:00
LisoUseInAIKyrios
77a9a56e2d Merge remote-tracking branch 'upstream/dev' into upstream-dev 2024-03-28 17:15:53 +04:00
LisoUseInAIKyrios
3df3441385 chore: fix typo 2024-03-28 17:15:40 +04:00
19 changed files with 217 additions and 81 deletions

39
.github/workflows/sync_crowdin.yml vendored Normal file
View File

@@ -0,0 +1,39 @@
name: Sync Crowdin
on:
workflow_dispatch:
schedule:
- cron: 0 * 1 * *
push:
paths:
- /src/main/resources/addresources/values/strings.xml
jobs:
sync:
name: Sync translations
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Sync translations
uses: crowdin/github-action@v1
with:
config: crowdin.yml
upload_sources: true
upload_translations: false
download_translations: true
localization_branch_name: feat/translations
create_pull_request: true
pull_request_title: "chore: Sync translations"
pull_request_body: "Sync translations from [crowdin.com/project/revanced](https://crowdin.com/project/revanced)"
pull_request_base_branch_name: "dev"
commit_message: "chore: Sync translations"
github_user_name: revanced-bot
github_user_email: github@revanced.app
env:
GITHUB_TOKEN: ${{ secrets.REPOSITORY_PUSH_ACCESS }}
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}

View File

@@ -1,3 +1,32 @@
## [4.5.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.5.0...v4.5.1-dev.1) (2024-03-30)
### Bug Fixes
* **Tumblr:** Restore compatibility with latest versions ([#2955](https://github.com/ReVanced/revanced-patches/issues/2955)) ([2954ba7](https://github.com/ReVanced/revanced-patches/commit/2954ba78d21d77308404961f79234bbec606d42e))
# [4.5.0](https://github.com/ReVanced/revanced-patches/compare/v4.4.0...v4.5.0) (2024-03-30)
### Features
* **YouTube - Alternative thumbnails:** Selectively enable for home / subscription / search ([#2926](https://github.com/ReVanced/revanced-patches/issues/2926)) ([8549e1b](https://github.com/ReVanced/revanced-patches/commit/8549e1ba58ad1e1608f5e3ceacd31eeb94578949))
* **YouTube - GmsCore:** Require ignoring battery optimizations ([#2952](https://github.com/ReVanced/revanced-patches/issues/2952)) ([c0bef25](https://github.com/ReVanced/revanced-patches/commit/c0bef255909ca884838675ca6f7ac5b0e2e21730))
# [4.5.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.5.0-dev.1...v4.5.0-dev.2) (2024-03-30)
### Features
* **YouTube - GmsCore:** Require ignoring battery optimizations ([#2952](https://github.com/ReVanced/revanced-patches/issues/2952)) ([c0bef25](https://github.com/ReVanced/revanced-patches/commit/c0bef255909ca884838675ca6f7ac5b0e2e21730))
# [4.5.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.4.0...v4.5.0-dev.1) (2024-03-29)
### Features
* **YouTube - Alternative thumbnails:** Selectively enable for home / subscription / search ([#2926](https://github.com/ReVanced/revanced-patches/issues/2926)) ([8549e1b](https://github.com/ReVanced/revanced-patches/commit/8549e1ba58ad1e1608f5e3ceacd31eeb94578949))
# [4.4.0](https://github.com/ReVanced/revanced-patches/compare/v4.3.0...v4.4.0) (2024-03-27) # [4.4.0](https://github.com/ReVanced/revanced-patches/compare/v4.3.0...v4.4.0) (2024-03-27)

8
crowdin.yml Normal file
View File

@@ -0,0 +1,8 @@
project_id_env: "CROWDIN_PROJECT_ID"
api_token_env: "CROWDIN_PERSONAL_TOKEN"
preserve_hierarchy: false
files:
- source: src/main/resources/addresources/values/strings.xml
translation: src/main/resources/addresources/values-%android_code%/strings.xml
skip_untranslated_strings: true

View File

@@ -1,4 +1,4 @@
org.gradle.parallel = true org.gradle.parallel = true
org.gradle.caching = true org.gradle.caching = true
kotlin.code.style = official kotlin.code.style = official
version = 4.4.0 version = 4.5.1-dev.1

View File

@@ -34,5 +34,5 @@ object GmsCoreSupportPatch : BaseGmsCoreSupportPatch(
PrimeMethodFingerprint, PrimeMethodFingerprint,
), ),
) { ) {
override val gmsCoreVendor by gmsCoreVendorGroupIdOption override val gmsCoreVendorGroupId by gmsCoreVendorGroupIdOption
} }

View File

@@ -2,7 +2,7 @@ package app.revanced.patches.shared.misc.gms
import app.revanced.patcher.PatchClass import app.revanced.patcher.PatchClass
import app.revanced.patcher.data.BytecodeContext 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.getInstructions import app.revanced.patcher.extensions.InstructionExtensions.getInstructions
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patcher.fingerprint.MethodFingerprint
@@ -12,7 +12,7 @@ import app.revanced.patches.shared.misc.gms.BaseGmsCoreSupportPatch.Constants.AC
import app.revanced.patches.shared.misc.gms.BaseGmsCoreSupportPatch.Constants.AUTHORITIES import app.revanced.patches.shared.misc.gms.BaseGmsCoreSupportPatch.Constants.AUTHORITIES
import app.revanced.patches.shared.misc.gms.BaseGmsCoreSupportPatch.Constants.PERMISSIONS import app.revanced.patches.shared.misc.gms.BaseGmsCoreSupportPatch.Constants.PERMISSIONS
import app.revanced.patches.shared.misc.gms.fingerprints.GmsCoreSupportFingerprint import app.revanced.patches.shared.misc.gms.fingerprints.GmsCoreSupportFingerprint
import app.revanced.patches.shared.misc.gms.fingerprints.GmsCoreSupportFingerprint.GET_GMS_CORE_VENDOR_METHOD_NAME import app.revanced.patches.shared.misc.gms.fingerprints.GmsCoreSupportFingerprint.GET_GMS_CORE_VENDOR_GROUP_ID_METHOD_NAME
import app.revanced.util.exception import app.revanced.util.exception
import app.revanced.util.getReference import app.revanced.util.getReference
import app.revanced.util.returnEarly import app.revanced.util.returnEarly
@@ -32,7 +32,7 @@ import com.android.tools.smali.dexlib2.util.MethodUtil
* @param toPackageName The package name to fall back to if no custom package name is specified in patch options. * @param toPackageName The package name to fall back to if no custom package name is specified in patch options.
* @param primeMethodFingerprint The fingerprint of the "prime" method that needs to be patched. * @param primeMethodFingerprint The fingerprint of the "prime" method that needs to be patched.
* @param earlyReturnFingerprints The fingerprints of methods that need to be returned early. * @param earlyReturnFingerprints The fingerprints of methods that need to be returned early.
* @param mainActivityOnCreateFingerprint The fingerprint of the main activity's onCreate method. * @param mainActivityOnCreateFingerprint The fingerprint of the main activity onCreate method.
* @param integrationsPatchDependency The patch responsible for the integrations. * @param integrationsPatchDependency The patch responsible for the integrations.
* @param gmsCoreSupportResourcePatch The corresponding resource patch that is used to patch the resources. * @param gmsCoreSupportResourcePatch The corresponding resource patch that is used to patch the resources.
* @param dependencies Additional dependencies of this patch. * @param dependencies Additional dependencies of this patch.
@@ -60,7 +60,10 @@ abstract class BaseGmsCoreSupportPatch(
integrationsPatchDependency, integrationsPatchDependency,
) + dependencies, ) + dependencies,
compatiblePackages = compatiblePackages, compatiblePackages = compatiblePackages,
fingerprints = setOf(GmsCoreSupportFingerprint, mainActivityOnCreateFingerprint) + fingerprints, fingerprints = setOf(
GmsCoreSupportFingerprint,
mainActivityOnCreateFingerprint,
) + fingerprints,
requiresIntegrations = true, requiresIntegrations = true,
) { ) {
init { init {
@@ -68,7 +71,7 @@ abstract class BaseGmsCoreSupportPatch(
gmsCoreSupportResourcePatch.options.values.forEach(options::register) gmsCoreSupportResourcePatch.options.values.forEach(options::register)
} }
internal abstract val gmsCoreVendor: String? internal abstract val gmsCoreVendorGroupId: String?
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
val packageName = ChangePackageNamePatch.setOrGetFallbackPackageName(toPackageName) val packageName = ChangePackageNamePatch.setOrGetFallbackPackageName(toPackageName)
@@ -93,16 +96,17 @@ abstract class BaseGmsCoreSupportPatch(
// Return these methods early to prevent the app from crashing. // Return these methods early to prevent the app from crashing.
earlyReturnFingerprints.toList().returnEarly() earlyReturnFingerprints.toList().returnEarly()
// Check the availability of GmsCore. // Verify GmsCore is installed and whitelisted for power optimizations and background usage.
mainActivityOnCreateFingerprint.result?.mutableMethod?.addInstruction( mainActivityOnCreateFingerprint.result?.mutableMethod?.addInstructions(
1, // Hack to not disturb other patches (such as the integrations patch). 1, // Hack to not disturb other patches (such as the YTMusic integrations patch).
"invoke-static {}, Lapp/revanced/integrations/shared/GmsCoreSupport;->checkAvailability()V", "invoke-static/range { p0 .. p0 }, Lapp/revanced/integrations/shared/GmsCoreSupport;->" +
"checkGmsCore(Landroid/content/Context;)V",
) ?: throw mainActivityOnCreateFingerprint.exception ) ?: throw mainActivityOnCreateFingerprint.exception
// Change the vendor of GmsCore in ReVanced Integrations. // Change the vendor of GmsCore in ReVanced Integrations.
GmsCoreSupportFingerprint.result?.mutableClass?.methods GmsCoreSupportFingerprint.result?.mutableClass?.methods
?.single { it.name == GET_GMS_CORE_VENDOR_METHOD_NAME } ?.single { it.name == GET_GMS_CORE_VENDOR_GROUP_ID_METHOD_NAME }
?.replaceInstruction(0, "const-string v0, \"$gmsCoreVendor\"") ?.replaceInstruction(0, "const-string v0, \"$gmsCoreVendorGroupId\"")
?: throw GmsCoreSupportFingerprint.exception ?: throw GmsCoreSupportFingerprint.exception
} }
@@ -146,10 +150,10 @@ abstract class BaseGmsCoreSupportPatch(
in PERMISSIONS, in PERMISSIONS,
in ACTIONS, in ACTIONS,
in AUTHORITIES, in AUTHORITIES,
-> referencedString.replace("com.google", gmsCoreVendor!!) -> referencedString.replace("com.google", gmsCoreVendorGroupId!!)
// No vendor prefix for whatever reason... // No vendor prefix for whatever reason...
"subscribedfeeds" -> "$gmsCoreVendor.subscribedfeeds" "subscribedfeeds" -> "$gmsCoreVendorGroupId.subscribedfeeds"
else -> null else -> null
} }
@@ -162,7 +166,7 @@ abstract class BaseGmsCoreSupportPatch(
if (str.startsWith(uriPrefix)) { if (str.startsWith(uriPrefix)) {
return str.replace( return str.replace(
uriPrefix, uriPrefix,
"content://${authority.replace("com.google", gmsCoreVendor!!)}", "content://${authority.replace("com.google", gmsCoreVendorGroupId!!)}",
) )
} }
} }
@@ -170,7 +174,7 @@ abstract class BaseGmsCoreSupportPatch(
// gms also has a 'subscribedfeeds' authority, check for that one too // gms also has a 'subscribedfeeds' authority, check for that one too
val subFeedsUriPrefix = "content://subscribedfeeds" val subFeedsUriPrefix = "content://subscribedfeeds"
if (str.startsWith(subFeedsUriPrefix)) { if (str.startsWith(subFeedsUriPrefix)) {
return str.replace(subFeedsUriPrefix, "content://$gmsCoreVendor.subscribedfeeds") return str.replace(subFeedsUriPrefix, "content://$gmsCoreVendorGroupId.subscribedfeeds")
} }
} }

View File

@@ -121,7 +121,6 @@ abstract class BaseGmsCoreSupportResourcePatch(
} }
private companion object { private companion object {
private const val VANCED_VENDOR = "com.mgoogle"
private const val PACKAGE_NAME_REGEX_PATTERN = "^[a-z]\\w*(\\.[a-z]\\w*)+\$" private const val PACKAGE_NAME_REGEX_PATTERN = "^[a-z]\\w*(\\.[a-z]\\w*)+\$"
} }
} }

View File

@@ -5,7 +5,7 @@ import app.revanced.patcher.fingerprint.MethodFingerprint
internal object GmsCoreSupportFingerprint : MethodFingerprint( internal object GmsCoreSupportFingerprint : MethodFingerprint(
customFingerprint = { _, classDef -> customFingerprint = { _, classDef ->
classDef.type.endsWith("GmsCoreSupport;") classDef.type.endsWith("GmsCoreSupport;")
} },
) { ) {
const val GET_GMS_CORE_VENDOR_METHOD_NAME = "getGmsCoreVendor" const val GET_GMS_CORE_VENDOR_GROUP_ID_METHOD_NAME = "getGmsCoreVendorGroupId"
} }

View File

@@ -1,9 +1,12 @@
package app.revanced.patches.tumblr.annoyances.popups.fingerprints package app.revanced.patches.tumblr.annoyances.popups.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
// This method is responsible for loading and displaying the visual Layout of the Gift Message Popup. // This method is responsible for loading and displaying the visual Layout of the Gift Message Popup.
internal object ShowGiftMessagePopupFingerprint : MethodFingerprint( internal object ShowGiftMessagePopupFingerprint : MethodFingerprint(
strings = listOf("activity", "anchorView"), strings = listOf("activity", "anchorView", "textMessage"),
customFingerprint = { methodDef, _ -> methodDef.definingClass.endsWith("GiftMessagePopup;") } returnType = "V",
accessFlags = AccessFlags.FINAL or AccessFlags.PUBLIC
) )

View File

@@ -28,6 +28,9 @@ object OverrideFeatureFlagsPatch : BytecodePatch(
internal lateinit var addOverride: (name: String, value: String) -> Unit private set internal lateinit var addOverride: (name: String, value: String) -> Unit private set
override fun execute(context: BytecodeContext) = GetFeatureValueFingerprint.result?.let { override fun execute(context: BytecodeContext) = GetFeatureValueFingerprint.result?.let {
val configurationClass = it.method.definingClass
val featureClass = it.method.parameterTypes[0].toString()
// The method we want to inject into does not have enough registers, so we inject a helper method // The method we want to inject into does not have enough registers, so we inject a helper method
// and inject more instructions into it later, see addOverride. // and inject more instructions into it later, see addOverride.
// This is not in an integration since the unused variable would get compiled away and the method would // This is not in an integration since the unused variable would get compiled away and the method would
@@ -35,7 +38,7 @@ object OverrideFeatureFlagsPatch : BytecodePatch(
val helperMethod = ImmutableMethod( val helperMethod = ImmutableMethod(
it.method.definingClass, it.method.definingClass,
"getValueOverride", "getValueOverride",
listOf(ImmutableMethodParameter("Lcom/tumblr/configuration/Feature;", null, "feature")), listOf(ImmutableMethodParameter(featureClass, null, "feature")),
"Ljava/lang/String;", "Ljava/lang/String;",
AccessFlags.PUBLIC or AccessFlags.FINAL, AccessFlags.PUBLIC or AccessFlags.FINAL,
null, null,
@@ -50,7 +53,7 @@ object OverrideFeatureFlagsPatch : BytecodePatch(
0, 0,
""" """
# toString() the enum value # toString() the enum value
invoke-virtual {p1}, Lcom/tumblr/configuration/Feature;->toString()Ljava/lang/String; invoke-virtual {p1}, $featureClass->toString()Ljava/lang/String;
move-result-object v0 move-result-object v0
# !!! If you add more instructions above this line, update helperInsertIndex below! # !!! If you add more instructions above this line, update helperInsertIndex below!
@@ -75,7 +78,7 @@ object OverrideFeatureFlagsPatch : BytecodePatch(
getFeatureIndex, getFeatureIndex,
""" """
# Call the Helper Method with the Feature # Call the Helper Method with the Feature
invoke-virtual {p0, p1}, Lcom/tumblr/configuration/Configuration;->getValueOverride(Lcom/tumblr/configuration/Feature;)Ljava/lang/String; invoke-virtual {p0, p1}, $configurationClass->getValueOverride($featureClass)Ljava/lang/String;
move-result-object v0 move-result-object v0
# If it returned null, skip # If it returned null, skip
if-eqz v0, :is_null if-eqz v0, :is_null

View File

@@ -1,6 +1,8 @@
package app.revanced.patches.tumblr.featureflags.fingerprints package app.revanced.patches.tumblr.featureflags.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint 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.Opcode
// This fingerprint targets the method to get the value of a Feature in the class "com.tumblr.configuration.Feature". // This fingerprint targets the method to get the value of a Feature in the class "com.tumblr.configuration.Feature".
@@ -19,5 +21,7 @@ internal object GetFeatureValueFingerprint : MethodFingerprint(
Opcode.INVOKE_STATIC, Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT Opcode.MOVE_RESULT
), ),
customFingerprint = { method, _ -> method.definingClass == "Lcom/tumblr/configuration/Configuration;" } returnType = "Ljava/lang/String;",
parameters = listOf("L", "Z"),
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL
) )

View File

@@ -8,11 +8,11 @@ import app.revanced.patches.tumblr.featureflags.OverrideFeatureFlagsPatch
import app.revanced.patches.tumblr.timelinefilter.TimelineFilterPatch import app.revanced.patches.tumblr.timelinefilter.TimelineFilterPatch
@Patch( @Patch(
name = "Disable Tumblr Live",
description = "Disable the Tumblr Live tab button and dashboard carousel.", description = "Disable the Tumblr Live tab button and dashboard carousel.",
dependencies = [OverrideFeatureFlagsPatch::class, TimelineFilterPatch::class], dependencies = [OverrideFeatureFlagsPatch::class, TimelineFilterPatch::class],
compatiblePackages = [CompatiblePackage("com.tumblr")], compatiblePackages = [CompatiblePackage("com.tumblr")],
) )
@Deprecated("Tumblr Live was removed and is no longer served in the feed, making this patch useless.")
@Suppress("unused") @Suppress("unused")
object DisableTumblrLivePatch : BytecodePatch(emptySet()) { object DisableTumblrLivePatch : BytecodePatch(emptySet()) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {

View File

@@ -14,7 +14,7 @@ import app.revanced.util.resultOrThrow
@Patch( @Patch(
name = "Downloads", name = "Downloads",
description = "Adds support to download videos with an external downloader app" + description = "Adds support to download videos with an external downloader app " +
"using the in-app download button or a video player action button.", "using the in-app download button or a video player action button.",
dependencies = [ dependencies = [
DownloadsResourcePatch::class, DownloadsResourcePatch::class,

View File

@@ -22,6 +22,8 @@ import app.revanced.patches.youtube.layout.thumbnails.fingerprints.cronet.reques
import app.revanced.patches.youtube.layout.thumbnails.fingerprints.cronet.request.callback.OnResponseStartedFingerprint import app.revanced.patches.youtube.layout.thumbnails.fingerprints.cronet.request.callback.OnResponseStartedFingerprint
import app.revanced.patches.youtube.layout.thumbnails.fingerprints.cronet.request.callback.OnSucceededFingerprint import app.revanced.patches.youtube.layout.thumbnails.fingerprints.cronet.request.callback.OnSucceededFingerprint
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.misc.navigation.NavigationBarHookPatch
import app.revanced.patches.youtube.misc.playertype.PlayerTypeHookPatch
import app.revanced.patches.youtube.misc.settings.SettingsPatch import app.revanced.patches.youtube.misc.settings.SettingsPatch
import app.revanced.util.resultOrThrow import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.AccessFlags
@@ -38,6 +40,8 @@ import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
IntegrationsPatch::class, IntegrationsPatch::class,
SettingsPatch::class, SettingsPatch::class,
AddResourcesPatch::class, AddResourcesPatch::class,
NavigationBarHookPatch::class,
PlayerTypeHookPatch::class
], ],
compatiblePackages = [ compatiblePackages = [
CompatiblePackage( CompatiblePackage(
@@ -127,25 +131,45 @@ object AlternativeThumbnailsPatch : BytecodePatch(
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
AddResourcesPatch(this::class) AddResourcesPatch(this::class)
val entries = "revanced_alt_thumbnail_options_entries"
val values = "revanced_alt_thumbnail_options_entry_values"
SettingsPatch.PreferenceScreen.ALTERNATIVE_THUMBNAILS.addPreferences( SettingsPatch.PreferenceScreen.ALTERNATIVE_THUMBNAILS.addPreferences(
NonInteractivePreference( ListPreference("revanced_alt_thumbnail_home",
"revanced_alt_thumbnail_about", summaryKey = null,
null, // Summary is dynamically updated based on the current settings. entriesKey = entries,
tag = "app.revanced.integrations.youtube.settings.preference.AlternativeThumbnailsStatusPreference", entryValuesKey = values
),
ListPreference("revanced_alt_thumbnail_subscription",
summaryKey = null,
entriesKey = entries,
entryValuesKey = values
),
ListPreference("revanced_alt_thumbnail_library",
summaryKey = null,
entriesKey = entries,
entryValuesKey = values
),
ListPreference("revanced_alt_thumbnail_player",
summaryKey = null,
entriesKey = entries,
entryValuesKey = values
),
ListPreference("revanced_alt_thumbnail_search",
summaryKey = null,
entriesKey = entries,
entryValuesKey = values
), ),
SwitchPreference("revanced_alt_thumbnail_dearrow"),
SwitchPreference("revanced_alt_thumbnail_dearrow_connection_toast"),
TextPreference("revanced_alt_thumbnail_dearrow_api_url"),
NonInteractivePreference( NonInteractivePreference(
"revanced_alt_thumbnail_dearrow_about", "revanced_alt_thumbnail_dearrow_about",
// Custom about preference with link to the DeArrow website. // Custom about preference with link to the DeArrow website.
tag = "app.revanced.integrations.youtube.settings.preference.AlternativeThumbnailsAboutDeArrowPreference", tag = "app.revanced.integrations.youtube.settings.preference.AlternativeThumbnailsAboutDeArrowPreference",
selectable = true, selectable = true,
), ),
SwitchPreference("revanced_alt_thumbnail_stills"), SwitchPreference("revanced_alt_thumbnail_dearrow_connection_toast"),
ListPreference("revanced_alt_thumbnail_stills_time", summaryKey = null), TextPreference("revanced_alt_thumbnail_dearrow_api_url"),
SwitchPreference("revanced_alt_thumbnail_stills_fast"),
NonInteractivePreference("revanced_alt_thumbnail_stills_about"), NonInteractivePreference("revanced_alt_thumbnail_stills_about"),
SwitchPreference("revanced_alt_thumbnail_stills_fast"),
ListPreference("revanced_alt_thumbnail_stills_time", summaryKey = null)
) )
fun MethodFingerprint.alsoResolve(fingerprint: MethodFingerprint) = fun MethodFingerprint.alsoResolve(fingerprint: MethodFingerprint) =

View File

@@ -2,16 +2,14 @@ package app.revanced.patches.youtube.misc.announcements
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstructions
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.all.misc.resources.AddResourcesPatch import app.revanced.patches.all.misc.resources.AddResourcesPatch
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
import app.revanced.patches.youtube.misc.settings.SettingsPatch import app.revanced.patches.youtube.misc.settings.SettingsPatch
import app.revanced.patches.youtube.shared.fingerprints.MainActivityFingerprint import app.revanced.patches.youtube.shared.fingerprints.MainActivityOnCreateFingerprint
import app.revanced.util.exception import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.Opcode
@Patch( @Patch(
name = "Announcements", name = "Announcements",
@@ -21,7 +19,7 @@ import com.android.tools.smali.dexlib2.Opcode
) )
@Suppress("unused") @Suppress("unused")
object AnnouncementsPatch : BytecodePatch( object AnnouncementsPatch : BytecodePatch(
setOf(MainActivityFingerprint) setOf(MainActivityOnCreateFingerprint)
) { ) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR = private const val INTEGRATIONS_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/youtube/patches/announcements/AnnouncementsPatch;" "Lapp/revanced/integrations/youtube/patches/announcements/AnnouncementsPatch;"
@@ -33,16 +31,11 @@ object AnnouncementsPatch : BytecodePatch(
SwitchPreference("revanced_announcements") SwitchPreference("revanced_announcements")
) )
val onCreateMethod = MainActivityFingerprint.result?.let { MainActivityOnCreateFingerprint.resultOrThrow().mutableMethod.addInstructions(
it.mutableClass.methods.find { method -> method.name == "onCreate" } // Insert index must be great than the insert index used by GmsCoreSupport,
} ?: throw MainActivityFingerprint.exception // as both patch the same method and GmsCore check should be first.
1,
val superCallIndex = onCreateMethod.getInstructions().indexOfFirst { it.opcode == Opcode.INVOKE_SUPER_RANGE } "invoke-static/range { p0 .. p0 }, $INTEGRATIONS_CLASS_DESCRIPTOR->showAnnouncement(Landroid/app/Activity;)V"
onCreateMethod.addInstructions(
superCallIndex + 1,
"invoke-static { v1 }, $INTEGRATIONS_CLASS_DESCRIPTOR->showAnnouncement(Landroid/app/Activity;)V"
) )
} }
} }

View File

@@ -9,7 +9,7 @@ import app.revanced.patches.youtube.misc.gms.Constants.YOUTUBE_PACKAGE_NAME
import app.revanced.patches.youtube.misc.gms.GmsCoreSupportResourcePatch.gmsCoreVendorGroupIdOption import app.revanced.patches.youtube.misc.gms.GmsCoreSupportResourcePatch.gmsCoreVendorGroupIdOption
import app.revanced.patches.youtube.misc.gms.fingerprints.* import app.revanced.patches.youtube.misc.gms.fingerprints.*
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.shared.fingerprints.HomeActivityFingerprint import app.revanced.patches.youtube.shared.fingerprints.MainActivityOnCreateFingerprint
@Suppress("unused") @Suppress("unused")
object GmsCoreSupportPatch : BaseGmsCoreSupportPatch( object GmsCoreSupportPatch : BaseGmsCoreSupportPatch(
@@ -23,7 +23,7 @@ object GmsCoreSupportPatch : BaseGmsCoreSupportPatch(
CastDynamiteModuleV2Fingerprint, CastDynamiteModuleV2Fingerprint,
CastContextFetchFingerprint, CastContextFetchFingerprint,
), ),
mainActivityOnCreateFingerprint = HomeActivityFingerprint, mainActivityOnCreateFingerprint = MainActivityOnCreateFingerprint,
integrationsPatchDependency = IntegrationsPatch::class, integrationsPatchDependency = IntegrationsPatch::class,
dependencies = setOf( dependencies = setOf(
HideCastButtonPatch::class, HideCastButtonPatch::class,
@@ -57,5 +57,5 @@ object GmsCoreSupportPatch : BaseGmsCoreSupportPatch(
PrimeMethodFingerprint, PrimeMethodFingerprint,
), ),
) { ) {
override val gmsCoreVendor by gmsCoreVendorGroupIdOption override val gmsCoreVendorGroupId by gmsCoreVendorGroupIdOption
} }

View File

@@ -0,0 +1,14 @@
package app.revanced.patches.youtube.shared.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
internal object MainActivityOnCreateFingerprint : MethodFingerprint(
returnType = "V",
parameters = listOf("Landroid/os/Bundle;"),
customFingerprint = { methodDef, classDef ->
methodDef.name == "onCreate" &&
(classDef.type.endsWith("MainActivity;")
// Old versions of YouTube called this class "WatchWhileActivity" instead.
|| classDef.type.endsWith("WatchWhileActivity;"))
}
)

View File

@@ -44,15 +44,28 @@
</string-array> </string-array>
</patch> </patch>
<patch id="layout.thumbnails.AlternativeThumbnailsPatch"> <patch id="layout.thumbnails.AlternativeThumbnailsPatch">
<string-array name="revanced_alt_thumbnail_options_entries">
<item>@string/revanced_alt_thumbnail_options_entry_1</item>
<item>@string/revanced_alt_thumbnail_options_entry_2</item>
<item>@string/revanced_alt_thumbnail_options_entry_3</item>
<item>@string/revanced_alt_thumbnail_options_entry_4</item>
</string-array>
<string-array name="revanced_alt_thumbnail_options_entry_values">
<!-- Enum names from Integrations -->
<item>ORIGINAL</item>
<item>DEARROW</item>
<item>DEARROW_STILL_IMAGES</item>
<item>STILL_IMAGES</item>
</string-array>
<string-array name="revanced_alt_thumbnail_stills_time_entries"> <string-array name="revanced_alt_thumbnail_stills_time_entries">
<item>@string/revanced_alt_thumbnail_stills_time_entry_1</item> <item>@string/revanced_alt_thumbnail_stills_time_entry_1</item>
<item>@string/revanced_alt_thumbnail_stills_time_entry_2</item> <item>@string/revanced_alt_thumbnail_stills_time_entry_2</item>
<item>@string/revanced_alt_thumbnail_stills_time_entry_3</item> <item>@string/revanced_alt_thumbnail_stills_time_entry_3</item>
</string-array> </string-array>
<string-array name="revanced_alt_thumbnail_stills_time_entry_values"> <string-array name="revanced_alt_thumbnail_stills_time_entry_values">
<item>1</item> <item>BEGINNING</item>
<item>2</item> <item>MIDDLE</item>
<item>3</item> <item>END</item>
</string-array> </string-array>
</patch> </patch>
<patch id="video.quality.RememberVideoQualityPatch"> <patch id="video.quality.RememberVideoQualityPatch">

View File

@@ -13,8 +13,12 @@
<string name="revanced_settings_import_failure_parse">Import failed: %s</string> <string name="revanced_settings_import_failure_parse">Import failed: %s</string>
</patch> </patch>
<patch id="misc.gms.BaseGmsCoreSupportResourcePatch"> <patch id="misc.gms.BaseGmsCoreSupportResourcePatch">
<string name="gms_core_not_installed_warning">GmsCore is not installed. Please install.</string> <string name="gms_core_toast_not_installed_message">GmsCore is not installed. Install it.</string>
<string name="gms_core_not_running_warning">GmsCore is failing to run. Please follow the \"Don\'t kill my app\" guide for GmsCore.</string> <string name="gms_core_toast_not_whitelisted_message">Follow the \"Don\'t kill my app\" guide for GmsCore.</string>
<string name="gms_core_dialog_title">Action needed</string>
<string name="gms_core_dialog_not_whitelisted_using_battery_optimizations_message">GmsCore is not whitelisted from battery optimization.\n\nFollow the \"Don\'t kill my app\" guide for GmsCore.</string>
<string name="gms_core_dialog_not_whitelisted_not_allowed_in_background_message">GmsCore does not have permission to run in the background.\n\nFollow the \"Don\'t kill my app\" guide for GmsCore.</string>
<string name="gms_core_dialog_ok_button_text">Open website</string>
</patch> </patch>
</app> </app>
<app id="youtube"> <app id="youtube">
@@ -847,33 +851,31 @@
<string name="revanced_seekbar_custom_color_invalid">Invalid seekbar color value. Using default value.</string> <string name="revanced_seekbar_custom_color_invalid">Invalid seekbar color value. Using default value.</string>
</patch> </patch>
<patch id="layout.thumbnails.AlternativeThumbnailsPatch"> <patch id="layout.thumbnails.AlternativeThumbnailsPatch">
<string name="revanced_alt_thumbnail_about_title">Thumbnails in use</string> <string name="revanced_alt_thumbnail_home_title">Home tab</string>
<string name="revanced_alt_thumbnail_dearrow_title">Enable DeArrow thumbnails</string> <string name="revanced_alt_thumbnail_subscription_title">Subscription tab</string>
<string name="revanced_alt_thumbnail_dearrow_summary_on">Using DeArrow thumbnails</string> <string name="revanced_alt_thumbnail_library_title">You tab</string>
<string name="revanced_alt_thumbnail_dearrow_summary_off">Not using DeArrow thumbnails</string> <string name="revanced_alt_thumbnail_player_title">Player playlists, recommendations</string>
<string name="revanced_alt_thumbnail_search_title">Search results</string>
<string name="revanced_alt_thumbnail_options_entry_1">Original thumbnails</string>
<string name="revanced_alt_thumbnail_options_entry_2">DeArrow &amp; Original thumbnails</string>
<string name="revanced_alt_thumbnail_options_entry_3">DeArrow &amp; Still captures</string>
<string name="revanced_alt_thumbnail_options_entry_4">Still captures</string>
<string name="revanced_alt_thumbnail_dearrow_about_title">DeArrow</string>
<string name="revanced_alt_thumbnail_dearrow_about_summary">DeArrow provides crowd-sourced thumbnails for YouTube videos. These thumbnails are often more relevant than those provided by YouTube\n\nIf enabled, video URLs will be sent to the API server and no other data is sent. If a video does not have DeArrow thumbnails, then the original or still captures are shown\n\nTap here to learn more about DeArrow</string>
<string name="revanced_alt_thumbnail_dearrow_connection_toast_title">Show a toast if API is not available</string> <string name="revanced_alt_thumbnail_dearrow_connection_toast_title">Show a toast if API is not available</string>
<string name="revanced_alt_thumbnail_dearrow_connection_toast_summary_on">Toast is shown if DeArrow is not available</string> <string name="revanced_alt_thumbnail_dearrow_connection_toast_summary_on">Toast is shown if DeArrow is not available</string>
<string name="revanced_alt_thumbnail_dearrow_connection_toast_summary_off">Toast is not shown if DeArrow is not available</string> <string name="revanced_alt_thumbnail_dearrow_connection_toast_summary_off">Toast is not shown if DeArrow is not available</string>
<string name="revanced_alt_thumbnail_dearrow_api_url_title">DeArrow API endpoint</string> <string name="revanced_alt_thumbnail_dearrow_api_url_title">DeArrow API endpoint</string>
<string name="revanced_alt_thumbnail_dearrow_api_url_summary">The URL of the DeArrow thumbnail cache endpoint. Do not change this unless you know what you\'re doing</string> <string name="revanced_alt_thumbnail_dearrow_api_url_summary">The URL of the DeArrow thumbnail cache endpoint</string>
<string name="revanced_alt_thumbnail_dearrow_about_title">About DeArrow</string> <string name="revanced_alt_thumbnail_stills_about_title">Still video captures</string>
<string name="revanced_alt_thumbnail_dearrow_about_summary">DeArrow provides crowd-sourced thumbnails for YouTube videos. These thumbnails are often more relevant than those provided by YouTube. If enabled, video URLs will be sent to the API server and no other data is sent\n\nTap here to learn more about DeArrow</string> <string name="revanced_alt_thumbnail_stills_about_summary">Still captures are taken from the beginning/middle/end of each video. These images are built into YouTube and no external API is used</string>
<string name="revanced_alt_thumbnail_stills_title">Enable still video captures</string>
<string name="revanced_alt_thumbnail_stills_summary_on">Using YouTube still video captures</string>
<string name="revanced_alt_thumbnail_stills_summary_off">Not using YouTube still video captures</string>
<string name="revanced_alt_thumbnail_stills_time_title">Video time to take the still from</string>
<string name="revanced_alt_thumbnail_stills_time_entry_1">Beginning of video</string>
<string name="revanced_alt_thumbnail_stills_time_entry_2">Middle of video</string>
<string name="revanced_alt_thumbnail_stills_time_entry_3">End of video</string>
<string name="revanced_alt_thumbnail_stills_fast_title">Use fast still captures</string> <string name="revanced_alt_thumbnail_stills_fast_title">Use fast still captures</string>
<string name="revanced_alt_thumbnail_stills_fast_summary_on">Using medium quality still captures. Thumbnails will load faster, but live streams, unreleased, or very old videos may show blank thumbnails</string> <string name="revanced_alt_thumbnail_stills_fast_summary_on">Using medium quality still captures. Thumbnails will load faster, but live streams, unreleased, or very old videos may show blank thumbnails</string>
<string name="revanced_alt_thumbnail_stills_fast_summary_off">Using high quality still captures</string> <string name="revanced_alt_thumbnail_stills_fast_summary_off">Using high quality still captures</string>
<string name="revanced_alt_thumbnail_stills_about_title">About still video captures</string> <string name="revanced_alt_thumbnail_stills_time_title">Video time to take still captures from</string>
<string name="revanced_alt_thumbnail_stills_about_summary">Still captures are taken from the beginning/middle/end of each video. These images are built into YouTube and no external API is used</string> <string name="revanced_alt_thumbnail_stills_time_entry_1">Beginning of video</string>
<string name="revanced_alt_thumbnail_about_status_disabled">Showing original YouTube thumbnails</string> <string name="revanced_alt_thumbnail_stills_time_entry_2">Middle of video</string>
<string name="revanced_alt_thumbnail_about_status_stills">Showing still video captures</string> <string name="revanced_alt_thumbnail_stills_time_entry_3">End of video</string>
<string name="revanced_alt_thumbnail_about_status_dearrow">Showing DeArrow thumbnails. If a video has no DeArrow thumbnails then the original YouTube thumbnails are shown</string>
<string name="revanced_alt_thumbnail_about_status_dearrow_stills">Showing DeArrow thumbnails. If a video has no DeArrow thumbnails then still video captures are shown</string>
<string name="revanced_alt_thumbnail_dearrow_error">DeArrow temporarily not available (status code: %s)</string> <string name="revanced_alt_thumbnail_dearrow_error">DeArrow temporarily not available (status code: %s)</string>
<string name="revanced_alt_thumbnail_dearrow_error_generic">DeArrow temporarily not available</string> <string name="revanced_alt_thumbnail_dearrow_error_generic">DeArrow temporarily not available</string>
</patch> </patch>
@@ -883,6 +885,7 @@
<string name="revanced_announcements_summary_off">Announcements are not shown on startup</string> <string name="revanced_announcements_summary_off">Announcements are not shown on startup</string>
<string name="revanced_announcements_enabled_summary">Show announcements on startup</string> <string name="revanced_announcements_enabled_summary">Show announcements on startup</string>
<string name="revanced_announcements_connection_failed">Failed connecting to announcements provider</string> <string name="revanced_announcements_connection_failed">Failed connecting to announcements provider</string>
<string name="revanced_announcements_dialog_dismiss">Dismiss</string>
</patch> </patch>
<patch id="misc.autorepeat.AutoRepeatPatch"> <patch id="misc.autorepeat.AutoRepeatPatch">
<string name="revanced_auto_repeat_title">Enable auto-repeat</string> <string name="revanced_auto_repeat_title">Enable auto-repeat</string>