From 03c995aa98285f26e5f00ff85b2ac66aebfb12ce Mon Sep 17 00:00:00 2001 From: eval Nya <60149113+nexplorer-3e@users.noreply.github.com> Date: Tue, 22 Apr 2025 13:19:41 +0800 Subject: [PATCH 1/3] feat: add MutualContact Co-authored-by: Eyre-S --- .../ioctl/tmoe/fragment/SettingsFragment.kt | 3 + .../tmoe/hook/func/MutualContactsBtnOption.kt | 93 +++++++++++++++++++ .../res/drawable/ic_round_swap_horiz_24.xml | 9 ++ app/src/main/res/values-es/strings.xml | 1 + app/src/main/res/values-ru/strings.xml | 1 + app/src/main/res/values-zh-rCN/strings.xml | 1 + app/src/main/res/values-zh-rTW/strings.xml | 1 + app/src/main/res/values/strings.xml | 1 + 8 files changed, 110 insertions(+) create mode 100644 app/src/main/java/cc/ioctl/tmoe/hook/func/MutualContactsBtnOption.kt create mode 100644 app/src/main/res/drawable/ic_round_swap_horiz_24.xml diff --git a/app/src/main/java/cc/ioctl/tmoe/fragment/SettingsFragment.kt b/app/src/main/java/cc/ioctl/tmoe/fragment/SettingsFragment.kt index 2e372ac5..45bdda3f 100644 --- a/app/src/main/java/cc/ioctl/tmoe/fragment/SettingsFragment.kt +++ b/app/src/main/java/cc/ioctl/tmoe/fragment/SettingsFragment.kt @@ -135,6 +135,9 @@ class SettingsFragment : BaseHierarchyFragment() { ShowIdInProfile, "ShowIdInProfile", R.string.ShowIdInProfile, "ShowIdInProfileDesc", R.string.ShowIdInProfileDesc ) + functionSwitch( + MutualContactsBtnOption, "MutualContact", R.string.MutualContact + ) } category("LostMsgMitigation", R.string.LostMsgMitigation) { functionSwitch( diff --git a/app/src/main/java/cc/ioctl/tmoe/hook/func/MutualContactsBtnOption.kt b/app/src/main/java/cc/ioctl/tmoe/hook/func/MutualContactsBtnOption.kt new file mode 100644 index 00000000..170cfa7c --- /dev/null +++ b/app/src/main/java/cc/ioctl/tmoe/hook/func/MutualContactsBtnOption.kt @@ -0,0 +1,93 @@ +package cc.ioctl.tmoe.hook.func + +import android.content.Context +import android.graphics.PorterDuff +import android.graphics.PorterDuffColorFilter +import android.graphics.drawable.Drawable +import android.view.Gravity +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import cc.ioctl.tmoe.R +import cc.ioctl.tmoe.base.annotation.FunctionHookEntry +import cc.ioctl.tmoe.hook.base.CommonDynamicHook +import cc.ioctl.tmoe.ui.LocaleController +import com.github.kyuubiran.ezxhelper.utils.* + + +@FunctionHookEntry +object MutualContactsBtnOption : CommonDynamicHook() { + object MutualViewTag + override fun initOnce(): Boolean = tryOrLogFalse { + val themeClzName = "org.telegram.ui.ActionBar.Theme" + val themeGetColor = findMethod(themeClzName) { name == "getColor" && parameterCount == 2 } + val themePlayerActionBarSelector = + findField(themeClzName) { name == "key_player_actionBarSelector" }.get(null) as Int + val themeWindowBackgroundWhiteGrayIcon = + findField(themeClzName) { name == "key_windowBackgroundWhiteGrayIcon" }.get(null) as Int + val themeCreateSelectorDrawable = + findMethod(themeClzName) { name == "createSelectorDrawable" } + + Log.dx("${MutualContactsBtnOption.javaClass.name}: before findUserCell") + findConstructor("org.telegram.ui.Cells.UserCell") { parameterTypes.size == 6 }.hookAfter { + if (!isEnabled) return@hookAfter + if (it.args[5] != null && it.args[5].javaClass.canonicalName != "$themeClzName.ResourcesProvider") return@hookAfter // neko workaround + val context = it.args[0] as Context + val resourcesProvider = it.args[5] + Log.dx("${MutualContactsBtnOption.javaClass.name}: findUserCell: init mutual view") + val mutualView = ImageView(context) + mutualView.tag = MutualViewTag + mutualView.setImageResource(R.drawable.ic_round_swap_horiz_24) + mutualView.scaleType = ImageView.ScaleType.CENTER + mutualView.visibility = View.GONE + mutualView.contentDescription = + LocaleController.getString("MutualContact", R.string.MutualContact) + mutualView.background = themeCreateSelectorDrawable.invoke( + null, + themeGetColor.invoke( + null, + themePlayerActionBarSelector, resourcesProvider + ) + ) as Drawable + mutualView.colorFilter = PorterDuffColorFilter( + themeGetColor.invoke( + null, + themeWindowBackgroundWhiteGrayIcon, resourcesProvider + ) as Int, PorterDuff.Mode.MULTIPLY + ) + mutualView.importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_NO + + val layoutHelperCreateFrame = + findMethod("org.telegram.ui.Components.LayoutHelper") { + name == "createFrame" && parameterCount == 7 + } + val tgIsRtl = + findField("org.telegram.messenger.LocaleController") { name == "isRTL" } + .get(null) as Boolean + (it.thisObject as ViewGroup).addView( + mutualView, + layoutHelperCreateFrame.invoke( + null, + 40, 40, + (if (tgIsRtl) Gravity.START else Gravity.END) or Gravity.CENTER_VERTICAL, + if (tgIsRtl) 8 else 0, 0, + if (tgIsRtl) 0 else 8, 0 + ) as ViewGroup.LayoutParams + ) + } + + Log.dx("${MutualContactsBtnOption.javaClass.name}: before findUpdate") + findMethod("org.telegram.ui.Cells.UserCell") { name == "update" }.hookAfter { + val mutualView = (it.thisObject as ViewGroup).findViewWithTag(MutualViewTag) + ?: return@hookAfter + val currObj = it.thisObject.findFieldObject { name == "currentObject" } + try { + if (currObj.getObject("mutual_contact") as Boolean) { + mutualView.visibility = View.VISIBLE + } + } catch (e: Exception) { + Log.d("${MutualContactsBtnOption.javaClass.name}: findUpdate: seems that not a user object") + } + } + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_round_swap_horiz_24.xml b/app/src/main/res/drawable/ic_round_swap_horiz_24.xml new file mode 100644 index 00000000..1ba2dbf2 --- /dev/null +++ b/app/src/main/res/drawable/ic_round_swap_horiz_24.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index b776b15f..a7556510 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -41,4 +41,5 @@ Añadir el botón de recarga de mensajes en el menú del chat Forzar la opción de desenfoque de la barra superior Desactivar la animación de pegatinas premium + Contacto mutuo diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 815c54b1..810530bb 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -60,6 +60,7 @@ История Повторить Дополнительные возможности + Общий контакт Не включен Еще не реализовано Запретить переключение каналов diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 097e6356..b17652fe 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -92,4 +92,5 @@ 参考 BuildVars.java 中的 LOGS_ENABLED(立即生效,重启失效) 拉取群成员列表? 如果您点击Telegram提供的广告,他们会收集数据作为个性化广告的基础。此功能用于屏蔽个性化广告。 + 双向联系人 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index cc7bc776..4bb9600f 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -94,4 +94,5 @@ 群組 / 频道 ID 使用者 ID 已複製 + 相互聯繫人 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index fe5c025a..36dbd04c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -98,4 +98,5 @@ Group / Channel ID User ID Copied + Mutual Contact From 95c295177c571ec119439438342d386588493676 Mon Sep 17 00:00:00 2001 From: eval Nya <60149113+nexplorer-3e@users.noreply.github.com> Date: Tue, 22 Apr 2025 13:42:26 +0800 Subject: [PATCH 2/3] fix(MutualContact): only add button when in contact book --- .../cc/ioctl/tmoe/hook/func/MutualContactsBtnOption.kt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/cc/ioctl/tmoe/hook/func/MutualContactsBtnOption.kt b/app/src/main/java/cc/ioctl/tmoe/hook/func/MutualContactsBtnOption.kt index 170cfa7c..790b4e22 100644 --- a/app/src/main/java/cc/ioctl/tmoe/hook/func/MutualContactsBtnOption.kt +++ b/app/src/main/java/cc/ioctl/tmoe/hook/func/MutualContactsBtnOption.kt @@ -18,6 +18,7 @@ import com.github.kyuubiran.ezxhelper.utils.* @FunctionHookEntry object MutualContactsBtnOption : CommonDynamicHook() { object MutualViewTag + var needAddMutual: Boolean = false; override fun initOnce(): Boolean = tryOrLogFalse { val themeClzName = "org.telegram.ui.ActionBar.Theme" val themeGetColor = findMethod(themeClzName) { name == "getColor" && parameterCount == 2 } @@ -28,9 +29,14 @@ object MutualContactsBtnOption : CommonDynamicHook() { val themeCreateSelectorDrawable = findMethod(themeClzName) { name == "createSelectorDrawable" } + Log.dx("${MutualContactsBtnOption.javaClass.name}: before onCreateViewHolder") + findMethod("org.telegram.ui.Adapters.ContactsAdapter") { name == "onCreateViewHolder" }.hookBefore { + needAddMutual = it.args[1] as Int == 0 + } + Log.dx("${MutualContactsBtnOption.javaClass.name}: before findUserCell") findConstructor("org.telegram.ui.Cells.UserCell") { parameterTypes.size == 6 }.hookAfter { - if (!isEnabled) return@hookAfter + if (!isEnabled || !needAddMutual) return@hookAfter if (it.args[5] != null && it.args[5].javaClass.canonicalName != "$themeClzName.ResourcesProvider") return@hookAfter // neko workaround val context = it.args[0] as Context val resourcesProvider = it.args[5] From 9bb70caa6c9d3d62ba04a471e8519616ef266aea Mon Sep 17 00:00:00 2001 From: eval Nya <60149113+nexplorer-3e@users.noreply.github.com> Date: Sat, 19 Jul 2025 12:43:04 +0800 Subject: [PATCH 3/3] chore: deps: use action-cache v4 --- .github/workflows/pr_ci.yml | 4 ++-- .github/workflows/push_ci.yml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pr_ci.yml b/.github/workflows/pr_ci.yml index 09df3116..faf787a3 100644 --- a/.github/workflows/pr_ci.yml +++ b/.github/workflows/pr_ci.yml @@ -28,7 +28,7 @@ jobs: cache: gradle - name: Cache Gradle Dependencies - uses: actions/cache@v3.2.4 + uses: actions/cache@v4 with: path: | ~/.gradle/caches @@ -39,7 +39,7 @@ jobs: gradle-deps - name: Cache Gradle Build - uses: actions/cache@v3.2.4 + uses: actions/cache@v4 with: path: | ~/.gradle/caches/build-cache-* diff --git a/.github/workflows/push_ci.yml b/.github/workflows/push_ci.yml index e6b53040..1fdee145 100644 --- a/.github/workflows/push_ci.yml +++ b/.github/workflows/push_ci.yml @@ -30,7 +30,7 @@ jobs: cache: gradle - name: Cache Gradle Dependencies - uses: actions/cache@v3.2.4 + uses: actions/cache@v4 with: path: | ~/.gradle/caches @@ -41,7 +41,7 @@ jobs: gradle-deps - name: Cache Gradle Build - uses: actions/cache@v3.2.4 + uses: actions/cache@v4 with: path: | ~/.gradle/caches/build-cache-* @@ -131,7 +131,7 @@ jobs: git status telegram-bot-api >> telegram-bot-api-status - name: Cache Bot API Binary id: cache-bot-api - uses: actions/cache@v3.2.4 + uses: actions/cache@v4 with: path: telegram-bot-api-binary key: CI-telegram-bot-api-${{ hashFiles('telegram-bot-api-status') }}