diff --git a/app/src/main/java/cc/ioctl/tmoe/hook/core/ProfileActivityRowHook.java b/app/src/main/java/cc/ioctl/tmoe/hook/core/ProfileActivityRowHook.java index 67820ee4..10128b6a 100644 --- a/app/src/main/java/cc/ioctl/tmoe/hook/core/ProfileActivityRowHook.java +++ b/app/src/main/java/cc/ioctl/tmoe/hook/core/ProfileActivityRowHook.java @@ -20,6 +20,7 @@ import cc.ioctl.tmoe.util.Utils; import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XposedBridge; +import de.robv.android.xposed.XposedHelpers; public class ProfileActivityRowHook implements Initializable { public static final ProfileActivityRowHook INSTANCE = new ProfileActivityRowHook(); @@ -116,6 +117,7 @@ private ProfileActivityRowHook() {} private static Class kProfileActivity = null; private static Field fProfileActivity_notificationRow = null; private static boolean sListViewOnItemClickListenerHooked = false; + private static ArrayList mPossibleIds = null; @Override public boolean initialize() { @@ -224,6 +226,37 @@ protected void afterHookedMethod(MethodHookParam param) throws Throwable { } } }); + XposedBridge.hookAllMethods( + Initiator.load("org.telegram.ui.ProfileActivity$DiffCallback"), "fillPositions", + new XC_MethodHook() { + @Override + protected void afterHookedMethod(MethodHookParam param) throws Throwable { + Object fragment = Reflex.getInstanceObjectOrNull(param.thisObject, "this$0"); + var args = (Bundle) fBaseFragment_arguments.get(fragment); + if (args == null) return; + var map = (HashMap) args.getSerializable(PROFILE_ACTIVITY_EXTRA_ROWS); + if (map == null) return; + var i = 1000; + for (var pos: map.keySet()) { + XposedHelpers.callMethod(param.thisObject, "put", ++i, pos, param.args[0]); + } + } + } + ); + // we only need to do this once + Field fProfileActivity_rowCount = kProfileActivity.getDeclaredField("rowCount"); + fProfileActivity_rowCount.setAccessible(true); + ArrayList possibleIds = new ArrayList<>(); + // find all private int fields whose value is -1 or 0 + for (Field f : kProfileActivity.getDeclaredFields()) { + if (f.getType() == int.class && !Modifier.isStatic(f.getModifiers())) { + f.setAccessible(true); + if (f.getName().endsWith("Row") || f.getName().endsWith("Row2")) { + possibleIds.add(f); + } + } + } + mPossibleIds = possibleIds; } catch (ReflectiveOperationException e) { Utils.loge(e); return false; @@ -268,31 +301,6 @@ protected void beforeHookedMethod(MethodHookParam param) { }; private static final XC_MethodHook SETTINGS_ROW_ID_ALLOCATOR = new XC_MethodHook(51) { - ArrayList mPossibleIds = null; - - @Override - protected void beforeHookedMethod(MethodHookParam param) throws Throwable { - if (mPossibleIds == null) { - // we only need to do this once - Field fProfileActivity_rowCount = kProfileActivity.getDeclaredField("rowCount"); - fProfileActivity_rowCount.setAccessible(true); - int currentRowCount = fProfileActivity_rowCount.getInt(param.thisObject); - if (currentRowCount == 0) { - ArrayList possibleIds = new ArrayList<>(); - // find all private int fields whose value is -1 or 0 - for (Field f : kProfileActivity.getDeclaredFields()) { - if (f.getType() == int.class && !Modifier.isStatic(f.getModifiers())) { - f.setAccessible(true); - int value = f.getInt(param.thisObject); - if (value == -1 || value == 0) { - possibleIds.add(f); - } - } - } - mPossibleIds = possibleIds; - } - } - } @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { diff --git a/app/src/main/java/cc/ioctl/tmoe/hook/func/ShowIdInProfile.kt b/app/src/main/java/cc/ioctl/tmoe/hook/func/ShowIdInProfile.kt index fb2d35e9..14b982bc 100644 --- a/app/src/main/java/cc/ioctl/tmoe/hook/func/ShowIdInProfile.kt +++ b/app/src/main/java/cc/ioctl/tmoe/hook/func/ShowIdInProfile.kt @@ -33,11 +33,11 @@ object ShowIdInProfile : CommonDynamicHook(), ProfileActivityRowHook.Callback { (Reflex.getInstanceObjectOrNull(holder, "itemView") as? FrameLayout)?.let { textCell -> Parasitics.injectModuleResources(HostInfo.getApplication().resources) val userId = getUserId(profileActivity) - val realId = if (userId == 0L) getChatId(profileActivity) else userId + val realId = if (userId == 0L) getChatOrTopicId(profileActivity) else userId.toString() val isUser = userId != 0L val title = if (isUser) LocaleController.getString("UserId", R.string.UserId) else LocaleController.getString("GroupOrChannelId", R.string.GroupOrChannelId) - XposedHelpers.callMethod(textCell, "setTextAndValue", realId.toString(), title, false) + XposedHelpers.callMethod(textCell, "setTextAndValue", realId, title, false) } return true } @@ -50,10 +50,10 @@ object ShowIdInProfile : CommonDynamicHook(), ProfileActivityRowHook.Callback { override fun onItemClicked(key: String, adapter: Any, profileActivity: Any): Boolean { if (rowName != key) return false val userId = getUserId(profileActivity) - val realId = if (userId == 0L) getChatId(profileActivity) else userId + val realId = if (userId == 0L) getChatOrTopicId(profileActivity) else userId.toString() val context = HostInfo.getApplication() context.getSystemService(ClipboardManager::class.java) - .setPrimaryClip(ClipData.newPlainText("", realId.toString())) + .setPrimaryClip(ClipData.newPlainText("", realId)) Toast.makeText(context, LocaleController.getString("IdCopied", R.string.IdCopied), Toast.LENGTH_SHORT).show() return true } @@ -62,20 +62,36 @@ object ShowIdInProfile : CommonDynamicHook(), ProfileActivityRowHook.Callback { manipulator: ProfileActivityRowHook.RowManipulator, profileActivity: Any ) { - var row = manipulator.getRowIdForField("infoHeaderRow") - row = if (row == -1) 1 else row + 1 + val row = manipulator.getRowIdForField("notificationsRow") + .let { nr -> + if (nr != -1) nr + else manipulator.getRowIdForField("infoHeaderRow").let { ihr -> + if (ihr == -1) 1 else ihr + 1 + } + } manipulator.insertRowAtPosition(rowName, row) } private fun getUserId(profileActivity: Any): Long { - return XposedHelpers.getObjectField(profileActivity, "userId") as Long + return (XposedHelpers.getObjectField(profileActivity, "userId") as Number).toLong() } private fun getChatId(profileActivity: Any): Long { val chat = XposedHelpers.getObjectField(profileActivity, "currentChat") if (chat != null) { - return XposedHelpers.getObjectField(chat, "id") as Long + return (XposedHelpers.getObjectField(chat, "id") as Number).toLong() } return 0L } + + private fun getTopicId(profileActivity: Any): Long { + return (XposedHelpers.getObjectField(profileActivity, "topicId") as Number).toLong() + } + + private fun getChatOrTopicId(profileActivity: Any): String { + val chatId = getChatId(profileActivity) + val topicId = getTopicId(profileActivity) + if (topicId == 0L) return chatId.toString() + return "$chatId/$topicId" + } } \ No newline at end of file