mirror of
https://github.com/rhunk/SnapEnhance.git
synced 2025-05-28 12:30:12 +02:00
feat: group chat menu
This commit is contained in:
parent
d18dff61d3
commit
6492cf3b48
@ -1,11 +1,11 @@
|
||||
package me.rhunk.snapenhance.features.impl.ui.menus
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.LinearLayout
|
||||
import de.robv.android.xposed.XposedBridge
|
||||
import me.rhunk.snapenhance.Constants
|
||||
import me.rhunk.snapenhance.config.ConfigProperty
|
||||
import me.rhunk.snapenhance.features.Feature
|
||||
@ -30,6 +30,12 @@ class MenuViewInjector : Feature("MenuViewInjector", loadParams = FeatureLoadPar
|
||||
context.resources.getString(context.resources.getIdentifier("new_chat", "string", Constants.SNAPCHAT_PACKAGE_NAME))
|
||||
}
|
||||
|
||||
private fun wasInjectedView(view: View): Boolean {
|
||||
if (view.getTag(Constants.VIEW_INJECTED_CODE) != null) return true
|
||||
view.setTag(Constants.VIEW_INJECTED_CODE, true)
|
||||
return false
|
||||
}
|
||||
|
||||
@SuppressLint("ResourceType")
|
||||
override fun asyncOnActivityCreate() {
|
||||
friendFeedInfoMenu.context = context
|
||||
@ -38,6 +44,9 @@ class MenuViewInjector : Feature("MenuViewInjector", loadParams = FeatureLoadPar
|
||||
settingMenu.context = context
|
||||
|
||||
val actionSheetItemsContainerLayoutId = context.resources.getIdentifier("action_sheet_items_container", "id", Constants.SNAPCHAT_PACKAGE_NAME)
|
||||
val actionSheetContainer = context.resources.getIdentifier("action_sheet_container", "id", Constants.SNAPCHAT_PACKAGE_NAME)
|
||||
val actionMenu = context.resources.getIdentifier("action_menu", "id", Constants.SNAPCHAT_PACKAGE_NAME)
|
||||
|
||||
val addViewMethod = ViewGroup::class.java.getMethod(
|
||||
"addView",
|
||||
View::class.java,
|
||||
@ -47,18 +56,12 @@ class MenuViewInjector : Feature("MenuViewInjector", loadParams = FeatureLoadPar
|
||||
|
||||
Hooker.hook(addViewMethod, HookStage.BEFORE) { param ->
|
||||
val viewGroup: ViewGroup = param.thisObject()
|
||||
val originalAddView: (View) -> Unit = { view: View ->
|
||||
XposedBridge.invokeOriginalMethod(
|
||||
addViewMethod,
|
||||
viewGroup,
|
||||
arrayOf(
|
||||
view,
|
||||
-1,
|
||||
FrameLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.MATCH_PARENT
|
||||
)
|
||||
)
|
||||
val originalAddView: (View) -> Unit = {
|
||||
param.invokeOriginal(arrayOf(it, -1,
|
||||
FrameLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.MATCH_PARENT
|
||||
))
|
||||
)
|
||||
}
|
||||
|
||||
@ -72,7 +75,34 @@ class MenuViewInjector : Feature("MenuViewInjector", loadParams = FeatureLoadPar
|
||||
return@hook
|
||||
}
|
||||
|
||||
//TODO : preview group chats
|
||||
//inject in group chat menus
|
||||
if (viewGroup.id == actionSheetContainer && childView.id == actionMenu) {
|
||||
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)
|
||||
}
|
||||
|
||||
Hooker.ephemeralHook(context.classCache.conversationManager, "fetchConversation", HookStage.AFTER) {
|
||||
if (wasInjectedView(injectedLayout)) return@ephemeralHook
|
||||
context.feature(Messaging::class).lastFetchConversationUserUUID = null
|
||||
|
||||
context.runOnUiThread {
|
||||
val viewList = mutableListOf<View>()
|
||||
friendFeedInfoMenu.inject(injectedLayout) { view ->
|
||||
view.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT).apply {
|
||||
setMargins(0, 10, 0, 10)
|
||||
}
|
||||
viewList.add(view)
|
||||
}
|
||||
viewList.reversed().forEach { injectedLayout.addView(it, 0) }
|
||||
}
|
||||
}
|
||||
|
||||
param.setArg(0, injectedLayout)
|
||||
}
|
||||
|
||||
if (viewGroup is LinearLayout && viewGroup.id == actionSheetItemsContainerLayoutId) {
|
||||
val itemStringInterface by lazy {
|
||||
childView.javaClass.declaredFields.filter {
|
||||
@ -87,7 +117,6 @@ class MenuViewInjector : Feature("MenuViewInjector", loadParams = FeatureLoadPar
|
||||
|
||||
//the 3 dot button shows a menu which contains the first item as a Plain object
|
||||
if (viewGroup.getChildCount() == 0 && itemStringInterface != null && itemStringInterface.toString().startsWith("Plain(primaryText=$newChatString")) {
|
||||
|
||||
settingMenu.inject(viewGroup, originalAddView)
|
||||
viewGroup.addOnAttachStateChangeListener(object: View.OnAttachStateChangeListener {
|
||||
override fun onViewAttachedToWindow(v: View) {}
|
||||
|
@ -223,7 +223,7 @@ class FriendFeedInfoMenu : AbstractMenu() {
|
||||
val friendFeedMenuOptions = context.config.options(ConfigProperty.FRIEND_FEED_MENU_BUTTONS)
|
||||
if (friendFeedMenuOptions.none { it.value }) return
|
||||
|
||||
val (conversationId, focusedConversationTargetUser) = getCurrentConversationId()
|
||||
val (conversationId, targetUser) = getCurrentConversationId()
|
||||
|
||||
if (!context.config.bool(ConfigProperty.ENABLE_FRIEND_FEED_MENU_BAR)) {
|
||||
//preview button
|
||||
@ -232,7 +232,7 @@ class FriendFeedInfoMenu : AbstractMenu() {
|
||||
ViewAppearanceHelper.applyTheme(this, viewModel.width)
|
||||
setOnClickListener {
|
||||
showPreview(
|
||||
focusedConversationTargetUser,
|
||||
targetUser,
|
||||
conversationId,
|
||||
context
|
||||
)
|
||||
@ -252,6 +252,14 @@ class FriendFeedInfoMenu : AbstractMenu() {
|
||||
}
|
||||
}
|
||||
|
||||
if (friendFeedMenuOptions["anti_auto_save"] == true) {
|
||||
createToggleFeature(viewConsumer,
|
||||
"friend_menu_option.anti_auto_save",
|
||||
{ context.feature(AntiAutoSave::class).isConversationIgnored(conversationId) },
|
||||
{ context.feature(AntiAutoSave::class).setConversationIgnored(conversationId, it) }
|
||||
)
|
||||
}
|
||||
|
||||
run {
|
||||
val userId = context.database.getFriendFeedInfoByConversationId(conversationId)?.friendUserId ?: return@run
|
||||
if (friendFeedMenuOptions["auto_download_blacklist"] == true) {
|
||||
@ -261,18 +269,14 @@ class FriendFeedInfoMenu : AbstractMenu() {
|
||||
{ context.feature(AntiAutoDownload::class).setUserIgnored(userId, it) }
|
||||
)
|
||||
}
|
||||
|
||||
if (friendFeedMenuOptions["anti_auto_save"] == true) {
|
||||
createToggleFeature(viewConsumer,
|
||||
"friend_menu_option.anti_auto_save",
|
||||
{ context.feature(AntiAutoSave::class).isConversationIgnored(conversationId) },
|
||||
{ context.feature(AntiAutoSave::class).setConversationIgnored(conversationId, it) }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
viewConsumer(stealthSwitch)
|
||||
viewConsumer(previewButton)
|
||||
if (friendFeedMenuOptions["stealth_mode"] == true) {
|
||||
viewConsumer(stealthSwitch)
|
||||
}
|
||||
if (friendFeedMenuOptions["conversation_info"] == true) {
|
||||
viewConsumer(previewButton)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@ -356,7 +360,7 @@ class FriendFeedInfoMenu : AbstractMenu() {
|
||||
//user
|
||||
createActionButton("\uD83D\uDC64") {
|
||||
showPreview(
|
||||
focusedConversationTargetUser,
|
||||
targetUser,
|
||||
conversationId,
|
||||
viewModel.context
|
||||
)
|
||||
|
@ -92,6 +92,19 @@ object Hooker {
|
||||
}.also { unhooks.addAll(it) }
|
||||
}
|
||||
|
||||
fun ephemeralHook(
|
||||
clazz: Class<*>,
|
||||
methodName: String,
|
||||
stage: HookStage,
|
||||
hookConsumer: (HookAdapter) -> Unit
|
||||
) {
|
||||
val unhooks: MutableSet<XC_MethodHook.Unhook> = HashSet()
|
||||
hook(clazz, methodName, stage) { param->
|
||||
hookConsumer(param)
|
||||
unhooks.forEach{ it.unhook() }
|
||||
}.also { unhooks.addAll(it) }
|
||||
}
|
||||
|
||||
fun ephemeralHookObjectMethod(
|
||||
clazz: Class<*>,
|
||||
instance: Any,
|
||||
|
Loading…
x
Reference in New Issue
Block a user