commit fb0180fc9d0e043399b63e942fbe9eab75f6a547
parent 4e3b393ea15163158c66fb2db896ca9b87a59622
Author: rhunk <101876869+rhunk@users.noreply.github.com>
Date:   Fri, 27 Oct 2023 16:16:47 +0200

fix(app/messaging_preview): conversation manager

Diffstat:
Mapp/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/social/MessagingPreview.kt | 20++++++++++++++++++++
Mcommon/src/main/aidl/me/rhunk/snapenhance/bridge/snapclient/MessagingBridge.aidl | 5+++++
Acommon/src/main/aidl/me/rhunk/snapenhance/bridge/snapclient/SessionStartListener.aidl | 6++++++
Mcommon/src/main/kotlin/me/rhunk/snapenhance/common/ReceiversConfig.kt | 1+
Mcore/src/main/kotlin/me/rhunk/snapenhance/core/SnapEnhance.kt | 2+-
Mcore/src/main/kotlin/me/rhunk/snapenhance/core/action/impl/ExportChatMessages.kt | 6+-----
Mcore/src/main/kotlin/me/rhunk/snapenhance/core/database/DatabaseAccess.kt | 19++++++++++++-------
Mcore/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/Messaging.kt | 15+++++++++------
Mcore/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/Notifications.kt | 2+-
Mcore/src/main/kotlin/me/rhunk/snapenhance/core/messaging/CoreMessagingBridge.kt | 13+++++++++++++
10 files changed, 69 insertions(+), 20 deletions(-)

diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/social/MessagingPreview.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/social/MessagingPreview.kt @@ -1,5 +1,6 @@ package me.rhunk.snapenhance.ui.manager.sections.social +import android.content.Intent import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.gestures.detectTapGestures @@ -25,7 +26,10 @@ import androidx.compose.ui.unit.dp import kotlinx.coroutines.* import me.rhunk.snapenhance.RemoteSideContext import me.rhunk.snapenhance.bridge.snapclient.MessagingBridge +import me.rhunk.snapenhance.bridge.snapclient.SessionStartListener import me.rhunk.snapenhance.bridge.snapclient.types.Message +import me.rhunk.snapenhance.common.Constants +import me.rhunk.snapenhance.common.ReceiversConfig import me.rhunk.snapenhance.common.data.ContentType import me.rhunk.snapenhance.common.data.SocialScope import me.rhunk.snapenhance.common.util.protobuf.ProtoReader @@ -421,6 +425,22 @@ class MessagingPreview( context.longToast("Failed to fetch conversation id") return } + if (!messagingBridge.isSessionStarted) { + context.androidContext.packageManager.getLaunchIntentForPackage( + Constants.SNAPCHAT_PACKAGE_NAME + )?.let { + val mainIntent = Intent.makeRestartActivityTask(it.component).apply { + putExtra(ReceiversConfig.MESSAGING_PREVIEW_EXTRA, true) + } + context.androidContext.startActivity(mainIntent) + } + messagingBridge.registerSessionStartListener(object: SessionStartListener.Stub() { + override fun onConnected() { + fetchNewMessages() + } + }) + return + } fetchNewMessages() } diff --git a/common/src/main/aidl/me/rhunk/snapenhance/bridge/snapclient/MessagingBridge.aidl b/common/src/main/aidl/me/rhunk/snapenhance/bridge/snapclient/MessagingBridge.aidl @@ -2,8 +2,13 @@ package me.rhunk.snapenhance.bridge.snapclient; import java.util.List; import me.rhunk.snapenhance.bridge.snapclient.types.Message; +import me.rhunk.snapenhance.bridge.snapclient.SessionStartListener; interface MessagingBridge { + boolean isSessionStarted(); + + void registerSessionStartListener(in SessionStartListener listener); + String getMyUserId(); @nullable Message fetchMessage(String conversationId, String clientMessageId); diff --git a/common/src/main/aidl/me/rhunk/snapenhance/bridge/snapclient/SessionStartListener.aidl b/common/src/main/aidl/me/rhunk/snapenhance/bridge/snapclient/SessionStartListener.aidl @@ -0,0 +1,5 @@ +package me.rhunk.snapenhance.bridge.snapclient; + +oneway interface SessionStartListener { + void onConnected(); +}+ \ No newline at end of file diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/ReceiversConfig.kt b/common/src/main/kotlin/me/rhunk/snapenhance/common/ReceiversConfig.kt @@ -4,4 +4,5 @@ object ReceiversConfig { const val BRIDGE_SYNC_ACTION = BuildConfig.APPLICATION_ID + ".core.bridge.SYNC" const val DOWNLOAD_REQUEST_EXTRA = "request" const val DOWNLOAD_METADATA_EXTRA = "metadata" + const val MESSAGING_PREVIEW_EXTRA = "messaging_preview" } \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/SnapEnhance.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/SnapEnhance.kt @@ -118,7 +118,6 @@ class SnapEnhance { logCritical(null, throwable) } } - bridgeClient.registerMessagingBridge(messagingBridge) reloadConfig() actionManager.init() @@ -136,6 +135,7 @@ class SnapEnhance { eventDispatcher.init() //if mappings aren't loaded, we can't initialize features if (!mappings.isMappingsLoaded()) return + bridgeClient.registerMessagingBridge(messagingBridge) features.init() scriptRuntime.connect(bridgeClient.getScriptingInterface()) syncRemote() diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/action/impl/ExportChatMessages.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/action/impl/ExportChatMessages.kt @@ -30,10 +30,6 @@ class ExportChatMessages : AbstractAction() { context.classCache.conversationManager.methods.first { it.name == "fetchConversationWithMessagesPaginated" } } - private val conversationManagerInstance by lazy { - context.feature(Messaging::class).conversationManager - } - private val dialogLogs = mutableListOf<String>() private var currentActionDialog: AlertDialog? = null @@ -165,7 +161,7 @@ class ExportChatMessages : AbstractAction() { }.build() fetchConversationWithMessagesPaginatedMethod.invoke( - conversationManagerInstance, + context.feature(Messaging::class).conversationManager, SnapUUID.fromString(conversationId).instanceNonNull(), lastMessageId, amount, diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/database/DatabaseAccess.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/database/DatabaseAccess.kt @@ -58,13 +58,18 @@ class DatabaseAccess( if (database != null && database.isOpen) return database } - return SQLiteDatabase.openDatabase( - context.androidContext.getDatabasePath(fileName).absolutePath, - null, - SQLiteDatabase.OPEN_READONLY - )?.also { - databaseWeakMap[fileName] = WeakReference(it) - } ?: throw IllegalStateException("Failed to open database $fileName") + return runCatching { + SQLiteDatabase.openDatabase( + context.androidContext.getDatabasePath(fileName).absolutePath, + null, + SQLiteDatabase.OPEN_READONLY + )?.also { + databaseWeakMap[fileName] = WeakReference(it) + } + }.onFailure { + context.log.error("Failed to open database $fileName, restarting!", it) + context.softRestartApp() + }.getOrNull() ?: throw IllegalStateException("Failed to open database $fileName") } private fun openMain() = openLocalDatabase("main.db") diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/Messaging.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/Messaging.kt @@ -1,5 +1,6 @@ package me.rhunk.snapenhance.core.features.impl.messaging +import me.rhunk.snapenhance.common.ReceiversConfig import me.rhunk.snapenhance.core.event.events.impl.OnSnapInteractionEvent import me.rhunk.snapenhance.core.features.Feature import me.rhunk.snapenhance.core.features.FeatureLoadParams @@ -12,10 +13,8 @@ import me.rhunk.snapenhance.core.wrapper.impl.SnapUUID class Messaging : Feature("Messaging", loadParams = FeatureLoadParams.ACTIVITY_CREATE_SYNC or FeatureLoadParams.INIT_ASYNC or FeatureLoadParams.INIT_SYNC) { private var _conversationManager: Any? = null - val conversationManager: Any - get() = _conversationManager ?: throw IllegalStateException("ConversationManager is not initialized").also { - context.longToast("Failed to get conversation manager. Please restart Snapchat") - } + val conversationManager: Any? + get() = _conversationManager var openedConversationUUID: SnapUUID? = null private set @@ -28,8 +27,12 @@ class Messaging : Feature("Messaging", loadParams = FeatureLoadParams.ACTIVITY_C private set override fun init() { - Hooker.hookConstructor(context.classCache.conversationManager, HookStage.BEFORE) { - _conversationManager = it.thisObject() + Hooker.hookConstructor(context.classCache.conversationManager, HookStage.BEFORE) { param -> + _conversationManager = param.thisObject() + context.messagingBridge.triggerSessionStart() + context.mainActivity?.takeIf { it.intent.getBooleanExtra(ReceiversConfig.MESSAGING_PREVIEW_EXTRA,false) }?.run { + finishAndRemoveTask() + } } } diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/Notifications.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/Notifications.kt @@ -315,7 +315,7 @@ class Notifications : Feature("Notifications", loadParams = FeatureLoadParams.IN notificationType.contains(it) }) return@hook - val conversationManager: Any = context.feature(Messaging::class).conversationManager + val conversationManager: Any = context.feature(Messaging::class).conversationManager ?: return@hook synchronized(notificationDataQueue) { notificationDataQueue[messageId.toLong()] = notificationData diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/messaging/CoreMessagingBridge.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/messaging/CoreMessagingBridge.kt @@ -3,6 +3,7 @@ package me.rhunk.snapenhance.core.messaging import kotlinx.coroutines.runBlocking import kotlinx.coroutines.suspendCancellableCoroutine import me.rhunk.snapenhance.bridge.snapclient.MessagingBridge +import me.rhunk.snapenhance.bridge.snapclient.SessionStartListener import me.rhunk.snapenhance.bridge.snapclient.types.Message import me.rhunk.snapenhance.core.ModContext import me.rhunk.snapenhance.core.features.impl.downloader.decoder.MessageDecoder @@ -28,6 +29,18 @@ class CoreMessagingBridge( private val context: ModContext ) : MessagingBridge.Stub() { private val conversationManager get() = context.feature(Messaging::class).conversationManager + private var sessionStartListener: SessionStartListener? = null + + fun triggerSessionStart() { + sessionStartListener?.onConnected() + sessionStartListener = null + } + + override fun isSessionStarted() = conversationManager != null + override fun registerSessionStartListener(listener: SessionStartListener) { + sessionStartListener = listener + } + override fun getMyUserId() = context.database.myUserId override fun fetchMessage(conversationId: String, clientMessageId: String): Message? {