feat(send_override): optional override dialog

- fix saveable snap in chat
This commit is contained in:
rhunk
2024-04-27 14:52:41 +02:00
parent ef8e2f9911
commit 21b4eea58f
5 changed files with 68 additions and 56 deletions

View File

@ -1059,6 +1059,7 @@
"abandon_video": "Missed Video Call"
},
"gallery_media_send_override": {
"always_ask": "Always Ask",
"ORIGINAL": "Original",
"NOTE": "Audio Note",
"SNAP": "Snap",

View File

@ -73,7 +73,7 @@ object DataProcessors {
val STRING_UNIQUE_SELECTION = PropertyDataProcessor(
type = Type.STRING_UNIQUE_SELECTION,
serialize = { JsonPrimitive(it) },
deserialize = { obj -> obj.takeIf { !it.isJsonNull }?.asString }
deserialize = { obj -> obj.takeIf { !it.isJsonNull }?.asString?.takeIf { it != "false" && it != "true" } }
)
val MAP_COORDINATES = PropertyDataProcessor(

View File

@ -94,7 +94,7 @@ class MessagingTweaks : ConfigContainer() {
customOptionTranslationPath = "features.options.notifications"
}
val messageLogger = container("message_logger", MessageLoggerConfig()) { addNotices(FeatureNotice.UNSTABLE); requireRestart() }
val galleryMediaSendOverride = boolean("gallery_media_send_override") { nativeHooks() }
val galleryMediaSendOverride = unique("gallery_media_send_override", "always_ask", "SNAP", "NOTE", "SAVABLE_SNAP") { requireRestart(); nativeHooks() }
val stripMediaMetadata = multiple("strip_media_metadata", "hide_caption_text", "hide_snap_filters", "hide_extras", "remove_audio_note_duration", "remove_audio_note_transcript_capability") { requireRestart() }
val bypassMessageRetentionPolicy = boolean("bypass_message_retention_policy") { addNotices(FeatureNotice.UNSTABLE); requireRestart() }
val bypassMessageActionRestrictions = boolean("bypass_message_action_restrictions") { requireRestart() }

View File

@ -176,7 +176,7 @@ class MediaFilePicker : Feature("Media File Picker", loadParams = FeatureLoadPar
val isAudio = context.androidContext.contentResolver.getType(event.intent.data!!)!!.startsWith("audio/")
if (isAudio || !context.config.messaging.galleryMediaSendOverride.get()) {
if (isAudio || context.config.messaging.galleryMediaSendOverride.getNullable() == null) {
startConversation(isAudio)
return@subscribe
}

View File

@ -1,5 +1,7 @@
package me.rhunk.snapenhance.core.features.impl.messaging
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.WarningAmber
import me.rhunk.snapenhance.common.data.ContentType
import me.rhunk.snapenhance.common.util.protobuf.ProtoEditor
import me.rhunk.snapenhance.common.util.protobuf.ProtoReader
@ -15,32 +17,14 @@ import me.rhunk.snapenhance.nativelib.NativeLib
class SendOverride : Feature("Send Override", loadParams = FeatureLoadParams.INIT_SYNC) {
private var isLastSnapSavable = false
private val typeNames by lazy {
mutableListOf(
"ORIGINAL",
"SNAP",
"NOTE"
).also {
mutableListOf("ORIGINAL", "SNAP", "NOTE").also {
if (NativeLib.initialized) {
it.add("SAVABLE_SNAP")
}
}.associateWith {
it
}
}.associateWith { it }
}
override fun init() {
context.event.subscribe(NativeUnaryCallEvent::class) { event ->
if (event.uri != "/messagingcoreservice.MessagingCoreService/CreateContentMessage") return@subscribe
if (isLastSnapSavable) {
val protoEditor = ProtoEditor(event.buffer)
protoEditor.edit(4) {
remove(7)
addVarInt(7, 3)
}
event.buffer = protoEditor.toByteArray()
}
}
val stripSnapMetadata = context.config.messaging.stripMediaMetadata.get()
context.event.subscribe(SendMessageWithContentEvent::class, {
@ -90,9 +74,28 @@ class SendOverride : Feature("Send Override", loadParams = FeatureLoadParams.INI
event.messageContent.content = newMessageContent
}
context.event.subscribe(SendMessageWithContentEvent::class, {
context.config.messaging.galleryMediaSendOverride.get()
}) { event ->
val configOverrideType = context.config.messaging.galleryMediaSendOverride.getNullable() ?: return
context.event.subscribe(NativeUnaryCallEvent::class) { event ->
if (event.uri != "/messagingcoreservice.MessagingCoreService/CreateContentMessage") return@subscribe
if (isLastSnapSavable) {
event.buffer = ProtoEditor(event.buffer).apply {
edit {
edit(4) {
remove(7)
addVarInt(7, 3) // savePolicy = VIEW_SESSION
}
add(6) {
from(9) {
addVarInt(1, 1)
}
}
}
}.toByteArray()
}
}
context.event.subscribe(SendMessageWithContentEvent::class) { event ->
isLastSnapSavable = false
if (event.destinations.stories?.isNotEmpty() == true && event.destinations.conversations?.isEmpty() == true) return@subscribe
val localMessageContent = event.messageContent
@ -104,22 +107,13 @@ class SendOverride : Feature("Send Override", loadParams = FeatureLoadParams.INI
event.canceled = true
context.runOnUiThread {
ViewAppearanceHelper.newAlertDialogBuilder(context.mainActivity!!)
.setItems(typeNames.values.map {
context.translation["features.options.gallery_media_send_override.$it"]
}.toTypedArray()) { dialog, which ->
dialog.dismiss()
val overrideType = typeNames.keys.toTypedArray()[which]
fun sendMedia(overrideType: String): Boolean {
if (overrideType != "ORIGINAL" && messageProtoReader.followPath(3)?.getCount(3) != 1) {
context.runOnUiThread {
ViewAppearanceHelper.newAlertDialogBuilder(context.mainActivity!!)
.setMessage(context.translation["gallery_media_send_override.multiple_media_toast"])
.setPositiveButton(context.translation["button.ok"], null)
.show()
}
return@setItems
context.inAppOverlay.showStatusToast(
icon = Icons.Default.WarningAmber,
context.translation["gallery_media_send_override.multiple_media_toast"]
)
return false
}
when (overrideType) {
@ -132,7 +126,6 @@ class SendOverride : Feature("Send Override", loadParams = FeatureLoadParams.INI
isLastSnapSavable = true
}
}
"NOTE" -> {
localMessageContent.contentType = ContentType.NOTE
localMessageContent.content =
@ -140,8 +133,26 @@ class SendOverride : Feature("Send Override", loadParams = FeatureLoadParams.INI
}
}
return true
}
if (configOverrideType != "always_ask") {
if (sendMedia(configOverrideType)) {
event.invokeOriginal()
}
return@subscribe
}
context.runOnUiThread {
ViewAppearanceHelper.newAlertDialogBuilder(context.mainActivity!!)
.setItems(typeNames.values.map {
context.translation["features.options.gallery_media_send_override.$it"]
}.toTypedArray()) { dialog, which ->
dialog.dismiss()
if (sendMedia(typeNames.keys.toTypedArray()[which])) {
event.invokeOriginal()
}
}
.setNegativeButton(context.translation["button.cancel"], null)
.show()
}