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.util.EvictingMap
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.hookConstructor
import me.rhunk.snapenhance.core.util.ktx.getObjectField
@ -31,16 +30,20 @@ class Messaging : Feature("Messaging", loadParams = FeatureLoadParams.ACTIVITY_C
var openedConversationUUID: SnapUUID? = null
private set
var lastFetchConversationUserUUID: SnapUUID? = null
var lastFocusedConversationId: String? = null
private set
var lastFetchConversationUUID: SnapUUID? = null
var lastFocusedConversationType: Int = -1
private set
var lastFetchGroupConversationUUID: SnapUUID? = null
var lastFocusedMessageId: Long = -1
private set
private val feedCachedSnapMessages = EvictingMap<String, List<Long>>(100)
fun resetLastFocusedConversation() {
lastFocusedConversationId = null
lastFocusedConversationType = -1
}
override fun init() {
context.classCache.conversationManager.hookConstructor(HookStage.BEFORE) { param ->
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 {
if (it.startsWith("null")) return@hook
}
context.database.getConversationType(conversationId)?.takeIf { it == 1 }?.run {
lastFetchGroupConversationUUID = SnapUUID(conversationId)
}
lastFocusedConversationId = 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 }
}
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 {
hook("enterConversation", HookStage.BEFORE) { param ->
openedConversationUUID = SnapUUID(param.arg(0))
@ -166,7 +155,7 @@ class Messaging : Feature("Messaging", loadParams = FeatureLoadParams.ACTIVITY_C
val stealthMode = context.feature(StealthMode::class)
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())
}) {
it.setResult(null)
@ -184,8 +173,10 @@ class Messaging : Feature("Messaging", loadParams = FeatureLoadParams.ACTIVITY_C
}
context.classCache.conversationManager.hook("fetchMessage", HookStage.BEFORE) { param ->
lastFetchConversationUserUUID = SnapUUID((param.arg(0) as Any))
lastFocusedMessageId = param.arg(1)
val conversationId = SnapUUID(param.arg(0)).toString()
if (openedConversationUUID?.toString() == conversationId) {
lastFocusedMessageId = param.arg(1)
}
}
context.classCache.conversationManager.hook("sendTypingNotification", HookStage.BEFORE, {

View File

@ -110,18 +110,12 @@ class MenuViewInjector : Feature("MenuViewInjector", loadParams = FeatureLoadPar
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 {
orientation = LinearLayout.VERTICAL
gravity = Gravity.BOTTOM
layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
addView(childView)
addOnAttachStateChangeListener(object: View.OnAttachStateChangeListener {
override fun onViewAttachedToWindow(v: View) {}
override fun onViewDetachedFromWindow(v: View) {
messaging.lastFetchGroupConversationUUID = null
}
})
}
event.parent.post {

View File

@ -259,30 +259,6 @@ class FriendFeedInfoMenu : AbstractMenu() {
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) {
viewConsumer(Switch(context.androidContext).apply {
text = this@FriendFeedInfoMenu.context.translation[value]
@ -301,7 +277,13 @@ class FriendFeedInfoMenu : AbstractMenu() {
val friendFeedMenuOptions by context.config.userInterface.friendFeedMenuButtons
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")
if (friendFeedMenuOptions.contains("conversation_info")) {