commit cb55923fd86dd5b5fb36799d483b9c4f98a7855b parent 25caf52dfe4faea8e925fdf48c39fbbb3f04495f Author: rhunk <101876869+rhunk@users.noreply.github.com> Date: Wed, 31 May 2023 17:27:25 +0200 fix(messagelogger): ui freezes & optimization Diffstat:
8 files changed, 53 insertions(+), 38 deletions(-)
diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/bridge/AbstractBridgeClient.kt b/app/src/main/kotlin/me/rhunk/snapenhance/bridge/AbstractBridgeClient.kt @@ -71,7 +71,7 @@ abstract class AbstractBridgeClient { * @param id the ID of the message logger message * @return the content of the message */ - abstract fun getMessageLoggerMessage(id: Long): ByteArray? + abstract fun getMessageLoggerMessage(conversationId: String, id: Long): ByteArray? /** * Add a message to the message logger database @@ -79,14 +79,14 @@ abstract class AbstractBridgeClient { * @param id the ID of the message logger message * @param message the content of the message */ - abstract fun addMessageLoggerMessage(id: Long, message: ByteArray) + abstract fun addMessageLoggerMessage(conversationId: String, id: Long, message: ByteArray) /** * Delete a message from the message logger database * * @param id the ID of the message logger message */ - abstract fun deleteMessageLoggerMessage(id: Long) + abstract fun deleteMessageLoggerMessage(conversationId: String, id: Long) /** * Clear the message logger database diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/bridge/MessageLoggerWrapper.kt b/app/src/main/kotlin/me/rhunk/snapenhance/bridge/MessageLoggerWrapper.kt @@ -12,33 +12,30 @@ class MessageLoggerWrapper( fun init() { database = SQLiteDatabase.openDatabase(databaseFile.absolutePath, null, SQLiteDatabase.CREATE_IF_NECESSARY or SQLiteDatabase.OPEN_READWRITE) - database.execSQL("CREATE TABLE IF NOT EXISTS messages (message_id INTEGER PRIMARY KEY, serialized_message BLOB)") + database.execSQL("CREATE TABLE IF NOT EXISTS messages (id INTEGER PRIMARY KEY, conversation_id VARCHAR, message_id BIGINT, message_data BLOB)") } - fun deleteMessage(messageId: Long) { - database.execSQL("DELETE FROM messages WHERE message_id = ?", arrayOf(messageId.toString())) + fun deleteMessage(conversationId: String, messageId: Long) { + database.execSQL("DELETE FROM messages WHERE conversation_id = ? AND message_id = ?", arrayOf(conversationId, messageId.toString())) } - fun addMessage(messageId: Long, serializedMessage: ByteArray): Boolean { - val cursor = database.rawQuery("SELECT message_id FROM messages WHERE message_id = ?", arrayOf(messageId.toString())) + fun addMessage(conversationId: String, messageId: Long, serializedMessage: ByteArray): Boolean { + val cursor = database.rawQuery("SELECT message_id FROM messages WHERE conversation_id = ? AND message_id = ?", arrayOf(conversationId, messageId.toString())) val state = cursor.moveToFirst() cursor.close() if (state) { return false } database.insert("messages", null, ContentValues().apply { + put("conversation_id", conversationId) put("message_id", messageId) - put("serialized_message", serializedMessage) + put("message_data", serializedMessage) }) return true } - fun clearMessages() { - database.execSQL("DELETE FROM messages") - } - - fun getMessage(messageId: Long): Pair<Boolean, ByteArray?> { - val cursor = database.rawQuery("SELECT serialized_message FROM messages WHERE message_id = ?", arrayOf(messageId.toString())) + fun getMessage(conversationId: String, messageId: Long): Pair<Boolean, ByteArray?> { + val cursor = database.rawQuery("SELECT message_data FROM messages WHERE conversation_id = ? AND message_id = ?", arrayOf(conversationId, messageId.toString())) val state = cursor.moveToFirst() val message: ByteArray? = if (state) { cursor.getBlob(0) @@ -48,4 +45,8 @@ class MessageLoggerWrapper( cursor.close() return Pair(state, message) } + + fun clearMessages() { + database.execSQL("DELETE FROM messages") + } } \ No newline at end of file diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/bridge/client/RootBridgeClient.kt b/app/src/main/kotlin/me/rhunk/snapenhance/bridge/client/RootBridgeClient.kt @@ -65,20 +65,20 @@ class RootBridgeClient : AbstractBridgeClient() { return true } - override fun getMessageLoggerMessage(id: Long): ByteArray? { - val (state, messageData) = messageLoggerWrapper.getMessage(id) + override fun getMessageLoggerMessage(conversationId: String, id: Long): ByteArray? { + val (state, messageData) = messageLoggerWrapper.getMessage(conversationId, id) if (state) { return messageData } return null } - override fun addMessageLoggerMessage(id: Long, message: ByteArray) { - messageLoggerWrapper.addMessage(id, message) + override fun addMessageLoggerMessage(conversationId: String, id: Long, message: ByteArray) { + messageLoggerWrapper.addMessage(conversationId, id, message) } - override fun deleteMessageLoggerMessage(id: Long) { - messageLoggerWrapper.deleteMessage(id) + override fun deleteMessageLoggerMessage(conversationId: String, id: Long) { + messageLoggerWrapper.deleteMessage(conversationId, id) } override fun clearMessageLogger() { diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/bridge/client/ServiceBridgeClient.kt b/app/src/main/kotlin/me/rhunk/snapenhance/bridge/client/ServiceBridgeClient.kt @@ -1,10 +1,12 @@ package me.rhunk.snapenhance.bridge.client +import android.annotation.TargetApi import android.content.ComponentName import android.content.Context import android.content.Intent import android.content.ServiceConnection +import android.os.Build import android.os.Bundle import android.os.Handler import android.os.HandlerThread @@ -38,6 +40,7 @@ class ServiceBridgeClient: AbstractBridgeClient(), ServiceConnection { private lateinit var messenger: Messenger private lateinit var future: CompletableFuture<Boolean> + @TargetApi(Build.VERSION_CODES.Q) override fun start(callback: (Boolean) -> Unit) { this.future = CompletableFuture() this.handlerThread.start() @@ -174,28 +177,28 @@ class ServiceBridgeClient: AbstractBridgeClient(), ServiceConnection { } } - override fun getMessageLoggerMessage(id: Long): ByteArray? { + override fun getMessageLoggerMessage(conversationId: String, id: Long): ByteArray? { sendMessage( BridgeMessageType.MESSAGE_LOGGER_REQUEST, - MessageLoggerRequest(MessageLoggerRequest.Action.GET, id), + MessageLoggerRequest(MessageLoggerRequest.Action.GET, conversationId, id), MessageLoggerResult::class ).run { return message } } - override fun addMessageLoggerMessage(id: Long, message: ByteArray) { + override fun addMessageLoggerMessage(conversationId: String,id: Long, message: ByteArray) { sendMessage( BridgeMessageType.MESSAGE_LOGGER_REQUEST, - MessageLoggerRequest(MessageLoggerRequest.Action.ADD, id, message), + MessageLoggerRequest(MessageLoggerRequest.Action.ADD, conversationId, id, message), MessageLoggerResult::class ) } - override fun deleteMessageLoggerMessage(id: Long) { + override fun deleteMessageLoggerMessage(conversationId: String,id: Long) { sendMessage( BridgeMessageType.MESSAGE_LOGGER_REQUEST, - MessageLoggerRequest(MessageLoggerRequest.Action.DELETE, id), + MessageLoggerRequest(MessageLoggerRequest.Action.DELETE, conversationId, id), MessageLoggerResult::class ) } @@ -203,7 +206,7 @@ class ServiceBridgeClient: AbstractBridgeClient(), ServiceConnection { override fun clearMessageLogger() { sendMessage( BridgeMessageType.MESSAGE_LOGGER_REQUEST, - MessageLoggerRequest(MessageLoggerRequest.Action.CLEAR, 0), + MessageLoggerRequest(MessageLoggerRequest.Action.CLEAR), MessageLoggerResult::class ) } diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/bridge/common/impl/messagelogger/MessageLoggerRequest.kt b/app/src/main/kotlin/me/rhunk/snapenhance/bridge/common/impl/messagelogger/MessageLoggerRequest.kt @@ -5,18 +5,21 @@ import me.rhunk.snapenhance.bridge.common.BridgeMessage class MessageLoggerRequest( var action: Action? = null, + var conversationId: String? = null, var messageId: Long? = null, var message: ByteArray? = null ) : BridgeMessage(){ override fun write(bundle: Bundle) { bundle.putString("action", action!!.name) + bundle.putString("conversationId", conversationId) bundle.putLong("messageId", messageId!!) bundle.putByteArray("message", message) } override fun read(bundle: Bundle) { action = Action.valueOf(bundle.getString("action")!!) + conversationId = bundle.getString("conversationId") messageId = bundle.getLong("messageId") message = bundle.getByteArray("message") } diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/bridge/service/BridgeService.kt b/app/src/main/kotlin/me/rhunk/snapenhance/bridge/service/BridgeService.kt @@ -82,7 +82,7 @@ class BridgeService : Service() { private fun handleMessageLoggerRequest(msg: MessageLoggerRequest, reply: (Message) -> Unit) { when (msg.action) { MessageLoggerRequest.Action.ADD -> { - val isSuccess = messageLoggerWrapper.addMessage(msg.messageId!!, msg.message!!) + val isSuccess = messageLoggerWrapper.addMessage(msg.conversationId!!, msg.messageId!!, msg.message!!) reply(MessageLoggerResult(isSuccess).toMessage(BridgeMessageType.MESSAGE_LOGGER_RESULT.value)) return } @@ -90,10 +90,10 @@ class BridgeService : Service() { messageLoggerWrapper.clearMessages() } MessageLoggerRequest.Action.DELETE -> { - messageLoggerWrapper.deleteMessage(msg.messageId!!) + messageLoggerWrapper.deleteMessage(msg.conversationId!!, msg.messageId!!) } MessageLoggerRequest.Action.GET -> { - val (state, messageData) = messageLoggerWrapper.getMessage(msg.messageId!!) + val (state, messageData) = messageLoggerWrapper.getMessage(msg.conversationId!!, msg.messageId!!) reply(MessageLoggerResult(state, messageData).toMessage(BridgeMessageType.MESSAGE_LOGGER_RESULT.value)) } else -> { diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/features/impl/spying/MessageLogger.kt b/app/src/main/kotlin/me/rhunk/snapenhance/features/impl/spying/MessageLogger.kt @@ -10,14 +10,19 @@ import me.rhunk.snapenhance.features.FeatureLoadParams import me.rhunk.snapenhance.hook.HookStage import me.rhunk.snapenhance.hook.Hooker -class MessageLogger : Feature("MessageLogger", loadParams = FeatureLoadParams.INIT_SYNC or FeatureLoadParams.ACTIVITY_CREATE_SYNC) { +class MessageLogger : Feature("MessageLogger", loadParams = FeatureLoadParams.INIT_SYNC or FeatureLoadParams.ACTIVITY_CREATE_ASYNC) { private val messageCache = mutableMapOf<Long, String>() private val removedMessages = linkedSetOf<Long>() private val myUserId by lazy { context.database.getMyUserId() } fun isMessageRemoved(messageId: Long) = removedMessages.contains(messageId) - override fun onActivityCreate() { + fun deleteMessage(conversationId: String, messageId: Long) { + messageCache.remove(messageId) + context.bridgeClient.deleteMessageLoggerMessage(conversationId, messageId) + } + + override fun asyncOnActivityCreate() { if (!context.database.hasArroyo()) { context.bridgeClient.clearMessageLogger() } @@ -31,15 +36,15 @@ class MessageLogger : Feature("MessageLogger", loadParams = FeatureLoadParams.IN val message = Message(it.thisObject()) val messageId = message.messageDescriptor.messageId val contentType = message.messageContent.contentType + val conversationId = message.messageDescriptor.conversationId.toString() val messageState = message.messageState if (messageState != MessageState.COMMITTED) return@hookConstructor - if (contentType == ContentType.STATUS) { //query the deleted message val deletedMessage: String = if (messageCache.containsKey(messageId)) messageCache[messageId] else { - context.bridgeClient.getMessageLoggerMessage(messageId)?.toString(Charsets.UTF_8) + context.bridgeClient.getMessageLoggerMessage(conversationId, messageId)?.toString(Charsets.UTF_8) } ?: return@hookConstructor val messageJsonObject = JsonParser.parseString(deletedMessage).asJsonObject @@ -72,10 +77,10 @@ class MessageLogger : Feature("MessageLogger", loadParams = FeatureLoadParams.IN if (!messageCache.containsKey(messageId)) { context.executeAsync { - val storedMessage = context.bridgeClient.getMessageLoggerMessage(messageId)?.toString(Charsets.UTF_8) + val storedMessage = context.bridgeClient.getMessageLoggerMessage(conversationId, messageId)?.toString(Charsets.UTF_8) if (storedMessage == null) { messageCache[messageId] = context.gson.toJson(message.instanceNonNull()) - context.bridgeClient.addMessageLoggerMessage(messageId, messageCache[messageId]!!.toByteArray(Charsets.UTF_8)) + context.bridgeClient.addMessageLoggerMessage(conversationId, messageId, messageCache[messageId]!!.toByteArray(Charsets.UTF_8)) return@executeAsync } messageCache[messageId] = storedMessage diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/features/impl/ui/menus/impl/ChatActionMenu.kt b/app/src/main/kotlin/me/rhunk/snapenhance/features/impl/ui/menus/impl/ChatActionMenu.kt @@ -15,6 +15,7 @@ import me.rhunk.snapenhance.Constants.VIEW_INJECTED_CODE import me.rhunk.snapenhance.config.ConfigProperty import me.rhunk.snapenhance.features.impl.Messaging import me.rhunk.snapenhance.features.impl.downloader.MediaDownloader +import me.rhunk.snapenhance.features.impl.spying.MessageLogger import me.rhunk.snapenhance.features.impl.ui.menus.AbstractMenu @@ -94,7 +95,9 @@ class ChatActionMenu : AbstractMenu() { downloadButton.setOnClickListener { closeActionMenu() context.executeAsync { - context.bridgeClient.deleteMessageLoggerMessage(context.feature(Messaging::class).lastFocusedMessageId) + with(context.feature(Messaging::class)) { + context.feature(MessageLogger::class).deleteMessage(lastOpenedConversationUUID.toString(), lastFocusedMessageId) + } } } parent.addView(downloadButton)