diff --git a/patches/src/main/kotlin/app/twitter/patches/DisableOutdatedVersionScreenPatch.kt b/patches/src/main/kotlin/app/twitter/patches/DisableOutdatedVersionScreenPatch.kt index c13ad40..3fd9aad 100644 --- a/patches/src/main/kotlin/app/twitter/patches/DisableOutdatedVersionScreenPatch.kt +++ b/patches/src/main/kotlin/app/twitter/patches/DisableOutdatedVersionScreenPatch.kt @@ -3,7 +3,9 @@ package app.twitter.patches import app.morphe.patcher.extensions.InstructionExtensions.addInstructions import app.morphe.patcher.Fingerprint import app.morphe.patcher.patch.bytecodePatch +import app.morphe.patcher.patch.resourcePatch import app.twitter.patches.shared.Constants.COMPATIBILITY_X +import org.w3c.dom.Element private val outdatedVersionEnforcementFingerprint = Fingerprint( definingClass = "Lcom/twitter/subsystem/clientshutdown/o;", @@ -13,6 +15,41 @@ private val outdatedVersionEnforcementFingerprint = Fingerprint( strings = listOf("Target version is ", "Detected shutdown") ) +private val forceUpdateNavigationFingerprint = Fingerprint( + definingClass = "Lcom/x/android/main/helpers/o8;", + name = "a", + returnType = "Lcom/x/compose/core/o2;", + parameters = listOf( + "Lcom/x/navigation/RootNavigationArgs;", + "Lcom/arkivanov/decompose/c;", + "Lcom/x/navigation/f1;" + ) +) + +private val shutdownForegroundHandlerFingerprint = Fingerprint( + definingClass = "Lcom/twitter/subsystem/clientshutdown/m;", + name = "invoke", + returnType = "Ljava/lang/Object;", + parameters = listOf("Ljava/lang/Object;"), + strings = listOf("Entered foreground, shutdown is ", "Launching app update") +) + +private val appUpdateLauncherFingerprint = Fingerprint( + definingClass = "Lcom/twitter/subsystem/clientshutdown/i;", + name = "a", + returnType = "V", + parameters = listOf("Ljava/lang/String;"), + strings = listOf("Launching app update") +) + +private val shutdownEntryPointDisablerFingerprint = Fingerprint( + definingClass = "Lcom/twitter/subsystem/clientshutdown/i;", + name = "b", + returnType = "V", + parameters = emptyList(), + strings = listOf("com.twitter.clientshutdown.update.AppUpdateActivityAlias") +) + private val shutdownStateFingerprint = Fingerprint( definingClass = "Lcom/twitter/subsystem/clientshutdown/q;", name = "isShutdown", @@ -20,6 +57,36 @@ private val shutdownStateFingerprint = Fingerprint( parameters = emptyList() ) +private const val APP_UPDATE_ACTIVITY = "com.twitter.clientshutdown.update.AppUpdateActivity" +private const val APP_UPDATE_ACTIVITY_ALIAS = "com.twitter.clientshutdown.update.AppUpdateActivityAlias" +private const val START_ACTIVITY = "com.twitter.android.StartActivity" + +private val disableOutdatedVersionActivityPatch = resourcePatch { + execute { + document("AndroidManifest.xml").use { document -> + val appUpdateActivity = document.getElementsByTagName("activity") + .let { activities -> + (0 until activities.length) + .asSequence() + .map { activities.item(it) } + .filterIsInstance() + .single { it.getAttribute("android:name") == APP_UPDATE_ACTIVITY } + } + appUpdateActivity.setAttribute("android:enabled", "false") + + val appUpdateActivityAlias = document.getElementsByTagName("activity-alias") + .let { aliases -> + (0 until aliases.length) + .asSequence() + .map { aliases.item(it) } + .filterIsInstance() + .single { it.getAttribute("android:name") == APP_UPDATE_ACTIVITY_ALIAS } + } + appUpdateActivityAlias.setAttribute("android:targetActivity", START_ACTIVITY) + } + } +} + @Suppress("unused") val disableOutdatedVersionScreenPatch = bytecodePatch( name = "Disable outdated version screen", @@ -27,8 +94,42 @@ val disableOutdatedVersionScreenPatch = bytecodePatch( default = true ) { compatibleWith(COMPATIBILITY_X) + dependsOn(disableOutdatedVersionActivityPatch) + execute { + forceUpdateNavigationFingerprint.method.addInstructions( + 0, + """ + move-object/from16 v2, p1 + instance-of v0, v2, Lcom/x/navigation/ForceUpdateArgs; + if-eqz v0, :force_update_allowed + sget-object v0, Lcom/x/navigation/MainLandingArgs${'$'}TabType;->HOME:Lcom/x/navigation/MainLandingArgs${'$'}TabType; + const/4 v1, 0x0 + new-instance v2, Lcom/x/navigation/MainLandingArgs; + invoke-direct {v2, v0, v1, v1, v1}, Lcom/x/navigation/MainLandingArgs;->(Lcom/x/navigation/MainLandingArgs${'$'}TabType;Lcom/x/navigation/AcceptGroupInviteArgs;Lcom/x/navigation/RootNavigationArgs;Lcom/x/models/PostIdentifier;)V + move-object/16 p1, v2 + :force_update_allowed + """ + ) + + shutdownForegroundHandlerFingerprint.method.addInstructions( + 0, + """ + sget-object v0, Lkotlin/Unit;->a:Lkotlin/Unit; + return-object v0 + """ + ) + + appUpdateLauncherFingerprint.method.addInstructions( + 0, + "return-void" + ) + + shutdownEntryPointDisablerFingerprint.method.addInstructions( + 0, + "return-void" + ) outdatedVersionEnforcementFingerprint.method.addInstructions( 0, """