fix(core/ui): messaging focus

This commit is contained in:
rhunk 2024-04-09 19:08:18 +02:00
parent 2651651be3
commit 454a441fda
3 changed files with 22 additions and 55 deletions

View File

@ -8,7 +8,6 @@ import me.rhunk.snapenhance.core.features.FeatureLoadParams
import me.rhunk.snapenhance.core.features.impl.spying.StealthMode import me.rhunk.snapenhance.core.features.impl.spying.StealthMode
import me.rhunk.snapenhance.core.util.EvictingMap import me.rhunk.snapenhance.core.util.EvictingMap
import me.rhunk.snapenhance.core.util.hook.HookStage import me.rhunk.snapenhance.core.util.hook.HookStage
import me.rhunk.snapenhance.core.util.hook.Hooker
import me.rhunk.snapenhance.core.util.hook.hook import me.rhunk.snapenhance.core.util.hook.hook
import me.rhunk.snapenhance.core.util.hook.hookConstructor import me.rhunk.snapenhance.core.util.hook.hookConstructor
import me.rhunk.snapenhance.core.util.ktx.getObjectField import me.rhunk.snapenhance.core.util.ktx.getObjectField
@ -31,16 +30,20 @@ class Messaging : Feature("Messaging", loadParams = FeatureLoadParams.ACTIVITY_C
var openedConversationUUID: SnapUUID? = null var openedConversationUUID: SnapUUID? = null
private set private set
var lastFetchConversationUserUUID: SnapUUID? = null var lastFocusedConversationId: String? = null
private set private set
var lastFetchConversationUUID: SnapUUID? = null var lastFocusedConversationType: Int = -1
private set private set
var lastFetchGroupConversationUUID: SnapUUID? = null
var lastFocusedMessageId: Long = -1 var lastFocusedMessageId: Long = -1
private set private set
private val feedCachedSnapMessages = EvictingMap<String, List<Long>>(100) private val feedCachedSnapMessages = EvictingMap<String, List<Long>>(100)
fun resetLastFocusedConversation() {
lastFocusedConversationId = null
lastFocusedConversationType = -1
}
override fun init() { override fun init() {
context.classCache.conversationManager.hookConstructor(HookStage.BEFORE) { param -> context.classCache.conversationManager.hookConstructor(HookStage.BEFORE) { param ->
conversationManager = ConversationManager(context, param.thisObject()) conversationManager = ConversationManager(context, param.thisObject())
@ -115,9 +118,8 @@ class Messaging : Feature("Messaging", loadParams = FeatureLoadParams.ACTIVITY_C
val conversationId = viewItem.substringAfter("conversationId: ").substring(0, 36).also { val conversationId = viewItem.substringAfter("conversationId: ").substring(0, 36).also {
if (it.startsWith("null")) return@hook if (it.startsWith("null")) return@hook
} }
context.database.getConversationType(conversationId)?.takeIf { it == 1 }?.run { lastFocusedConversationId = conversationId
lastFetchGroupConversationUUID = SnapUUID(conversationId) lastFocusedConversationType = context.database.getConversationType(conversationId) ?: 0
}
} }
} }
@ -133,19 +135,6 @@ class Messaging : Feature("Messaging", loadParams = FeatureLoadParams.ACTIVITY_C
}.sortedBy { it.orderKey }.mapNotNull { it.messageDescriptor?.messageId } }.sortedBy { it.orderKey }.mapNotNull { it.messageDescriptor?.messageId }
} }
context.mappings.useMapper(CallbackMapper::class) {
callbacks.getClass("GetOneOnOneConversationIdsCallback")?.hook("onSuccess", HookStage.BEFORE) { param ->
val userIdToConversation = (param.arg<ArrayList<*>>(0))
.takeIf { it.isNotEmpty() }
?.get(0) ?: return@hook
lastFetchConversationUUID =
SnapUUID(userIdToConversation.getObjectField("mConversationId"))
lastFetchConversationUserUUID =
SnapUUID(userIdToConversation.getObjectField("mUserId"))
}
}
context.classCache.conversationManager.apply { context.classCache.conversationManager.apply {
hook("enterConversation", HookStage.BEFORE) { param -> hook("enterConversation", HookStage.BEFORE) { param ->
openedConversationUUID = SnapUUID(param.arg(0)) openedConversationUUID = SnapUUID(param.arg(0))
@ -166,7 +155,7 @@ class Messaging : Feature("Messaging", loadParams = FeatureLoadParams.ACTIVITY_C
val stealthMode = context.feature(StealthMode::class) val stealthMode = context.feature(StealthMode::class)
arrayOf("activate", "deactivate", "processTypingActivity").forEach { hook -> arrayOf("activate", "deactivate", "processTypingActivity").forEach { hook ->
Hooker.hook(context.classCache.presenceSession, hook, HookStage.BEFORE, { context.classCache.presenceSession.hook(hook, HookStage.BEFORE, {
context.config.messaging.hideBitmojiPresence.get() || stealthMode.canUseRule(openedConversationUUID.toString()) context.config.messaging.hideBitmojiPresence.get() || stealthMode.canUseRule(openedConversationUUID.toString())
}) { }) {
it.setResult(null) it.setResult(null)
@ -184,8 +173,10 @@ class Messaging : Feature("Messaging", loadParams = FeatureLoadParams.ACTIVITY_C
} }
context.classCache.conversationManager.hook("fetchMessage", HookStage.BEFORE) { param -> context.classCache.conversationManager.hook("fetchMessage", HookStage.BEFORE) { param ->
lastFetchConversationUserUUID = SnapUUID((param.arg(0) as Any)) val conversationId = SnapUUID(param.arg(0)).toString()
lastFocusedMessageId = param.arg(1) if (openedConversationUUID?.toString() == conversationId) {
lastFocusedMessageId = param.arg(1)
}
} }
context.classCache.conversationManager.hook("sendTypingNotification", HookStage.BEFORE, { context.classCache.conversationManager.hook("sendTypingNotification", HookStage.BEFORE, {

View File

@ -110,18 +110,12 @@ class MenuViewInjector : Feature("MenuViewInjector", loadParams = FeatureLoadPar
return@subscribe return@subscribe
} }
if (viewGroup !is LinearLayout && childView.id == actionMenu && messaging.lastFetchGroupConversationUUID != null) { if (viewGroup !is LinearLayout && childView.id == actionMenu && messaging.lastFocusedConversationType == 1) {
val injectedLayout = LinearLayout(childView.context).apply { val injectedLayout = LinearLayout(childView.context).apply {
orientation = LinearLayout.VERTICAL orientation = LinearLayout.VERTICAL
gravity = Gravity.BOTTOM gravity = Gravity.BOTTOM
layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
addView(childView) addView(childView)
addOnAttachStateChangeListener(object: View.OnAttachStateChangeListener {
override fun onViewAttachedToWindow(v: View) {}
override fun onViewDetachedFromWindow(v: View) {
messaging.lastFetchGroupConversationUUID = null
}
})
} }
event.parent.post { event.parent.post {

View File

@ -259,30 +259,6 @@ class FriendFeedInfoMenu : AbstractMenu() {
builder.show() builder.show()
} }
private fun getCurrentConversationInfo(): Pair<String, String?> {
val messaging = context.feature(Messaging::class)
val focusedConversationTargetUser: String? = messaging.lastFetchConversationUserUUID?.toString()
//mapped conversation fetch (may not work with legacy sc versions)
messaging.lastFetchGroupConversationUUID?.let {
context.database.getFeedEntryByConversationId(it.toString())?.let { friendFeedInfo ->
val participantSize = friendFeedInfo.participantsSize
return it.toString() to if (participantSize == 1) focusedConversationTargetUser else null
}
throw IllegalStateException("No conversation found")
}
//old conversation fetch
val conversationId = if (messaging.lastFetchConversationUUID == null && focusedConversationTargetUser != null) {
val conversation: UserConversationLink = context.database.getConversationLinkFromUserId(focusedConversationTargetUser) ?: throw IllegalStateException("No conversation found")
conversation.clientConversationId!!.trim().lowercase()
} else {
messaging.lastFetchConversationUUID.toString()
}
return conversationId to focusedConversationTargetUser
}
private fun createToggleFeature(viewConsumer: ((View) -> Unit), value: String, checked: () -> Boolean, toggle: (Boolean) -> Unit) { private fun createToggleFeature(viewConsumer: ((View) -> Unit), value: String, checked: () -> Boolean, toggle: (Boolean) -> Unit) {
viewConsumer(Switch(context.androidContext).apply { viewConsumer(Switch(context.androidContext).apply {
text = this@FriendFeedInfoMenu.context.translation[value] text = this@FriendFeedInfoMenu.context.translation[value]
@ -301,7 +277,13 @@ class FriendFeedInfoMenu : AbstractMenu() {
val friendFeedMenuOptions by context.config.userInterface.friendFeedMenuButtons val friendFeedMenuOptions by context.config.userInterface.friendFeedMenuButtons
if (friendFeedMenuOptions.isEmpty()) return if (friendFeedMenuOptions.isEmpty()) return
val (conversationId, targetUser) = getCurrentConversationInfo() val messaging = context.feature(Messaging::class)
val conversationId = messaging.lastFocusedConversationId ?: run {
context.shortToast("No conversation focused!")
return
}
val targetUser = context.database.getDMOtherParticipant(conversationId)
messaging.resetLastFocusedConversation()
val translation = context.translation.getCategory("friend_menu_option") val translation = context.translation.getCategory("friend_menu_option")
if (friendFeedMenuOptions.contains("conversation_info")) { if (friendFeedMenuOptions.contains("conversation_info")) {