fix(app/messaging_preview): conversation manager

This commit is contained in:
rhunk 2023-10-27 16:16:47 +02:00
parent 4e3b393ea1
commit fb0180fc9d
10 changed files with 68 additions and 20 deletions

View File

@ -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()
}

View File

@ -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);

View File

@ -0,0 +1,5 @@
package me.rhunk.snapenhance.bridge.snapclient;
oneway interface SessionStartListener {
void onConnected();
}

View File

@ -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"
}

View File

@ -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()

View File

@ -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,

View File

@ -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")

View File

@ -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()
}
}
}

View File

@ -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

View File

@ -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? {