commit 553664771d64cf519420687200677707e62947ad
parent 865a8953b8e07cc113b9c51b639dddef04817d21
Author: rhunk <101876869+rhunk@users.noreply.github.com>
Date: Tue, 2 Apr 2024 21:08:00 +0200
fix(core/experimental): edit message
Diffstat:
5 files changed, 98 insertions(+), 69 deletions(-)
diff --git a/common/src/main/assets/lang/en_US.json b/common/src/main/assets/lang/en_US.json
@@ -1059,7 +1059,8 @@
"preview_button": "Preview",
"download_button": "Download",
"delete_logged_message_button": "Delete Logged Message",
- "convert_message": "Convert Message"
+ "convert_message": "Convert Message",
+ "edit_message": "Edit Message"
},
"opera_context_menu": {
diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/ui/menu/AbstractMenu.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/ui/menu/AbstractMenu.kt
@@ -5,6 +5,7 @@ import android.view.ViewGroup
import me.rhunk.snapenhance.core.ModContext
abstract class AbstractMenu {
+ lateinit var menuViewInjector: MenuViewInjector
lateinit var context: ModContext
open fun inject(parent: ViewGroup, view: View, viewConsumer: (View) -> Unit) {}
diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/ui/menu/MenuViewInjector.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/ui/menu/MenuViewInjector.kt
@@ -13,11 +13,12 @@ import me.rhunk.snapenhance.core.features.FeatureLoadParams
import me.rhunk.snapenhance.core.features.impl.messaging.Messaging
import me.rhunk.snapenhance.core.ui.menu.impl.*
import me.rhunk.snapenhance.core.util.ktx.getIdentifier
+import kotlin.reflect.KClass
@SuppressLint("DiscouragedApi")
class MenuViewInjector : Feature("MenuViewInjector", loadParams = FeatureLoadParams.ACTIVITY_CREATE_ASYNC) {
- override fun asyncOnActivityCreate() {
- val menuMap = arrayOf(
+ private val menuMap by lazy {
+ arrayOf(
NewChatActionMenu(),
OperaContextActionMenu(),
OperaDownloadIconMenu(),
@@ -27,9 +28,18 @@ class MenuViewInjector : Feature("MenuViewInjector", loadParams = FeatureLoadPar
SettingsMenu()
).associateBy {
it.context = context
- it.init()
+ it.menuViewInjector = this
it::class
}
+ }
+
+ @Suppress("UNCHECKED_CAST")
+ fun <T: AbstractMenu> menu(menuClass: KClass<T>): T? {
+ return menuMap[menuClass] as? T
+ }
+
+ override fun asyncOnActivityCreate() {
+ menuMap.forEach { it.value.init() }
val messaging = context.feature(Messaging::class)
diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/ui/menu/impl/ChatActionMenu.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/ui/menu/impl/ChatActionMenu.kt
@@ -4,17 +4,11 @@ import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup.MarginLayoutParams
import android.widget.Button
-import android.widget.EditText
import android.widget.LinearLayout
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.launch
-import me.rhunk.snapenhance.common.util.protobuf.ProtoReader
-import me.rhunk.snapenhance.common.util.protobuf.ProtoWriter
import me.rhunk.snapenhance.core.features.impl.downloader.MediaDownloader
import me.rhunk.snapenhance.core.features.impl.experiments.ConvertMessageLocally
import me.rhunk.snapenhance.core.features.impl.messaging.Messaging
import me.rhunk.snapenhance.core.features.impl.spying.MessageLogger
-import me.rhunk.snapenhance.core.ui.ViewAppearanceHelper
import me.rhunk.snapenhance.core.ui.ViewTagState
import me.rhunk.snapenhance.core.ui.applyTheme
import me.rhunk.snapenhance.core.ui.menu.AbstractMenu
@@ -141,66 +135,9 @@ class ChatActionMenu : AbstractMenu() {
if (context.config.experimental.editMessage.get() && messaging.conversationManager?.isEditMessageSupported() == true) {
injectButton(Button(viewGroup.context).apply button@{
- text = "Edit Message"
+ text = this@ChatActionMenu.context.translation["chat_action_menu.edit_message"]
setOnClickListener {
- messaging.conversationManager?.fetchMessage(
- messaging.openedConversationUUID.toString(),
- messaging.lastFocusedMessageId,
- onSuccess = onSuccess@{ message ->
- closeActionMenu()
- if (message.senderId.toString() != this@ChatActionMenu.context.database.myUserId) {
- this@ChatActionMenu.context.shortToast("You can only edit your own messages")
- return@onSuccess
- }
-
- val editText = EditText(viewGroup.context).apply {
- setText(ProtoReader(message.messageContent?.content ?: return@apply).getString(2, 1) ?: run {
- this@ChatActionMenu.context.shortToast("You can only edit text messages")
- return@onSuccess
- })
- setTextColor(resources.getColor(android.R.color.white, context.theme))
- postDelayed({
- requestFocus()
- setSelection(text.length)
- context.getSystemService(android.content.Context.INPUT_METHOD_SERVICE)
- .let { it as android.view.inputmethod.InputMethodManager }
- .showSoftInput(this, android.view.inputmethod.InputMethodManager.SHOW_IMPLICIT)
- }, 200)
- }
-
- this@ChatActionMenu.context.runOnUiThread {
- ViewAppearanceHelper.newAlertDialogBuilder(this@ChatActionMenu.context.mainActivity!!)
- .setPositiveButton("Save") { _, _ ->
- val newMessageContent = ProtoWriter().apply {
- from(2) { addString(1, editText.text.toString()) }
- }.toByteArray()
- message.messageContent?.content = newMessageContent
- messaging.conversationManager?.editMessage(
- message.messageDescriptor?.conversationId.toString(),
- message.messageDescriptor?.messageId ?: return@setPositiveButton,
- newMessageContent,
- onSuccess = {
- this@ChatActionMenu.context.coroutineScope.launch(Dispatchers.Main) {
- message.messageMetadata?.isEdited = true
- messaging.localUpdateMessage(
- message.messageDescriptor?.conversationId.toString(),
- message,
- forceUpdate = true
- )
- }
- },
- onError = {
- this@ChatActionMenu.context.shortToast("Failed to edit message: $it")
- }
- )
- }
- .setNegativeButton("Cancel") { dialog, _ -> dialog.dismiss() }
- .setView(editText)
- .setTitle("Edit message content")
- .show()
- }
- }
- )
+ menuViewInjector.menu(NewChatActionMenu::class)?.editCurrentMessage(context, closeActionMenu)
}
})
}
diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/ui/menu/impl/NewChatActionMenu.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/ui/menu/impl/NewChatActionMenu.kt
@@ -3,6 +3,7 @@ package me.rhunk.snapenhance.core.ui.menu.impl
import android.content.Context
import android.text.format.Formatter
import android.view.ViewGroup
+import android.widget.EditText
import android.widget.LinearLayout
import android.widget.ScrollView
import androidx.compose.foundation.border
@@ -14,6 +15,7 @@ import androidx.compose.material.icons.filled.Download
import androidx.compose.material.icons.filled.RemoveRedEye
import androidx.compose.material.icons.outlined.Image
import androidx.compose.material.icons.rounded.BookmarkRemove
+import androidx.compose.material.icons.rounded.Edit
import androidx.compose.material3.Button
import androidx.compose.material3.Card
import androidx.compose.material3.Icon
@@ -27,10 +29,13 @@ import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.unit.dp
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
import me.rhunk.snapenhance.common.data.ContentType
import me.rhunk.snapenhance.common.ui.createComposeView
import me.rhunk.snapenhance.common.util.ktx.copyToClipboard
import me.rhunk.snapenhance.common.util.protobuf.ProtoReader
+import me.rhunk.snapenhance.common.util.protobuf.ProtoWriter
import me.rhunk.snapenhance.common.util.snap.RemoteMediaResolver
import me.rhunk.snapenhance.core.event.events.impl.AddViewEvent
import me.rhunk.snapenhance.core.features.impl.downloader.MediaDownloader
@@ -65,6 +70,71 @@ class NewChatActionMenu : AbstractMenu() {
}
}
+ fun editCurrentMessage(
+ localContext: Context,
+ dismissActionMenu: () -> Unit,
+ ) {
+ val messaging = context.feature(Messaging::class)
+ messaging.conversationManager?.fetchMessage(
+ messaging.openedConversationUUID.toString(),
+ messaging.lastFocusedMessageId,
+ onSuccess = onSuccess@{ message ->
+ dismissActionMenu()
+ if (message.senderId.toString() != context.database.myUserId) {
+ context.shortToast("You can only edit your own messages")
+ return@onSuccess
+ }
+
+ val editText = EditText(localContext).apply {
+ setText(ProtoReader(message.messageContent?.content ?: return@apply).getString(2, 1) ?: run {
+ this@NewChatActionMenu.context.shortToast("You can only edit text messages")
+ return@onSuccess
+ })
+ setTextColor(resources.getColor(android.R.color.white, context.theme))
+ postDelayed({
+ requestFocus()
+ setSelection(text.length)
+ context.getSystemService(android.content.Context.INPUT_METHOD_SERVICE)
+ .let { it as android.view.inputmethod.InputMethodManager }
+ .showSoftInput(this, android.view.inputmethod.InputMethodManager.SHOW_IMPLICIT)
+ }, 200)
+ }
+
+ context.runOnUiThread {
+ ViewAppearanceHelper.newAlertDialogBuilder(context.mainActivity!!)
+ .setPositiveButton("Save") { _, _ ->
+ val newMessageContent = ProtoWriter().apply {
+ from(2) { addString(1, editText.text.toString()) }
+ }.toByteArray()
+ message.messageContent?.content = newMessageContent
+ messaging.conversationManager?.editMessage(
+ message.messageDescriptor?.conversationId.toString(),
+ message.messageDescriptor?.messageId ?: return@setPositiveButton,
+ newMessageContent,
+ onSuccess = {
+ context.coroutineScope.launch(Dispatchers.Main) {
+ message.messageMetadata?.isEdited = true
+ messaging.localUpdateMessage(
+ message.messageDescriptor?.conversationId.toString(),
+ message,
+ forceUpdate = true
+ )
+ }
+ },
+ onError = {
+ context.shortToast("Failed to edit message: $it")
+ }
+ )
+ }
+ .setNegativeButton("Cancel") { dialog, _ -> dialog.dismiss() }
+ .setView(editText)
+ .setTitle("Edit message content")
+ .show()
+ }
+ }
+ )
+ }
+
private val lastFocusedMessage
get() = context.database.getConversationMessageFromId(context.feature(Messaging::class).lastFocusedMessageId)
@@ -243,6 +313,16 @@ class NewChatActionMenu : AbstractMenu() {
})
}
+ if (context.config.experimental.editMessage.get() && messaging.conversationManager?.isEditMessageSupported() == true) {
+ ListButton(icon = Icons.Rounded.Edit, text = context.translation["chat_action_menu.edit_message"], modifier = Modifier.clickable {
+ editCurrentMessage(event.view.context) {
+ context.runOnUiThread {
+ closeActionMenu()
+ }
+ }
+ })
+ }
+
if (context.config.messaging.messageLogger.globalState == true) {
ListButton(icon = Icons.Rounded.BookmarkRemove, text = context.translation["chat_action_menu.delete_logged_message_button"], modifier = Modifier.clickable {
closeActionMenu()