commit 21b4eea58f554db650a900ef76db35e5ab9f3205
parent ef8e2f99115456fdf1d9d43213fcdf6dc39ce861
Author: rhunk <101876869+rhunk@users.noreply.github.com>
Date: Sat, 27 Apr 2024 14:52:41 +0200
feat(send_override): optional override dialog
- fix saveable snap in chat
Diffstat:
5 files changed, 68 insertions(+), 56 deletions(-)
diff --git a/common/src/main/assets/lang/en_US.json b/common/src/main/assets/lang/en_US.json
@@ -1059,6 +1059,7 @@
"abandon_video": "Missed Video Call"
},
"gallery_media_send_override": {
+ "always_ask": "Always Ask",
"ORIGINAL": "Original",
"NOTE": "Audio Note",
"SNAP": "Snap",
diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/config/DataProcessors.kt b/common/src/main/kotlin/me/rhunk/snapenhance/common/config/DataProcessors.kt
@@ -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(
diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/MessagingTweaks.kt b/common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/MessagingTweaks.kt
@@ -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() }
diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/MediaFilePicker.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/MediaFilePicker.kt
@@ -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
}
diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/SendOverride.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/SendOverride.kt
@@ -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,43 +107,51 @@ class SendOverride : Feature("Send Override", loadParams = FeatureLoadParams.INI
event.canceled = true
+ fun sendMedia(overrideType: String): Boolean {
+ if (overrideType != "ORIGINAL" && messageProtoReader.followPath(3)?.getCount(3) != 1) {
+ context.inAppOverlay.showStatusToast(
+ icon = Icons.Default.WarningAmber,
+ context.translation["gallery_media_send_override.multiple_media_toast"]
+ )
+ return false
+ }
+
+ when (overrideType) {
+ "SNAP", "SAVABLE_SNAP" -> {
+ val extras = messageProtoReader.followPath(3, 3, 13)?.getBuffer()
+
+ localMessageContent.contentType = ContentType.SNAP
+ localMessageContent.content = MessageSender.redSnapProto(extras)
+ if (overrideType == "SAVABLE_SNAP") {
+ isLastSnapSavable = true
+ }
+ }
+ "NOTE" -> {
+ localMessageContent.contentType = ContentType.NOTE
+ localMessageContent.content =
+ MessageSender.audioNoteProto(messageProtoReader.getVarInt(3, 3, 5, 1, 1, 15) ?: context.feature(MediaFilePicker::class).lastMediaDuration ?: 0)
+ }
+ }
+
+ 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()
- val overrideType = typeNames.keys.toTypedArray()[which]
-
- 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
- }
-
- when (overrideType) {
- "SNAP", "SAVABLE_SNAP" -> {
- val extras = messageProtoReader.followPath(3, 3, 13)?.getBuffer()
-
- localMessageContent.contentType = ContentType.SNAP
- localMessageContent.content = MessageSender.redSnapProto(extras)
- if (overrideType == "SAVABLE_SNAP") {
- isLastSnapSavable = true
- }
- }
-
- "NOTE" -> {
- localMessageContent.contentType = ContentType.NOTE
- localMessageContent.content =
- MessageSender.audioNoteProto(messageProtoReader.getVarInt(3, 3, 5, 1, 1, 15) ?: context.feature(MediaFilePicker::class).lastMediaDuration ?: 0)
- }
+ if (sendMedia(typeNames.keys.toTypedArray()[which])) {
+ event.invokeOriginal()
}
-
- event.invokeOriginal()
}
.setNegativeButton(context.translation["button.cancel"], null)
.show()