From abd50409653a493f6aa5d431e6d7a4eb3bdf0f88 Mon Sep 17 00:00:00 2001 From: mkx173 Date: Sun, 7 Apr 2024 15:07:26 -0700 Subject: [PATCH] feat: migrate TbDialog to native --- .../main/java/gm/tieba/tabswitch/Constants.kt | 4 +- .../java/gm/tieba/tabswitch/XposedInit.java | 10 +- .../tieba/tabswitch/hooker/TSPreference.java | 59 +++---- .../tabswitch/hooker/TSPreferenceHelper.java | 80 ++++++--- .../tabswitch/hooker/add/HistoryCache.java | 71 ++++++-- .../tabswitch/hooker/add/SelectClipboard.java | 7 +- .../hooker/eliminate/RegexFilter.java | 2 +- .../gm/tieba/tabswitch/util/DisplayUtils.java | 9 + .../java/gm/tieba/tabswitch/util/Parser.java | 3 +- .../gm/tieba/tabswitch/widget/TbDialog.java | 167 ------------------ 10 files changed, 157 insertions(+), 255 deletions(-) delete mode 100644 app/src/main/java/gm/tieba/tabswitch/widget/TbDialog.java diff --git a/app/src/main/java/gm/tieba/tabswitch/Constants.kt b/app/src/main/java/gm/tieba/tabswitch/Constants.kt index 0eb31442..2d91a554 100644 --- a/app/src/main/java/gm/tieba/tabswitch/Constants.kt +++ b/app/src/main/java/gm/tieba/tabswitch/Constants.kt @@ -8,8 +8,8 @@ object Constants { " ②本模块不会主动发起网络请求,不会上传任何用户数据,隐私泄露或者账号异常行为与本模块无关。\n" + " ③本模块主要用于学习和交流技术,任何人不得将本模块用于商业或非法用途。", "dev_tip" to "提示:您当前安装的是非正式版本,可能含有较多错误,如果您希望得到更稳定的使用体验,建议您安装正式版本。", - "exception_rules_incomplete" to "规则异常,请点击确定并重启应用以重新执行反混淆。若执行反混淆后仍出现此对话框则应尝试更新模块或向作者反馈。", - "version_mismatch" to "规则异常,当前贴吧版本不受支持。请使用受支持的贴吧版本(%s-%s)或尝试更新模块。", + "exception_rules_incomplete" to "请点击确定并重启应用以重新执行反混淆。若执行反混淆后仍出现此对话框则应尝试更新模块或向作者反馈。", + "version_mismatch" to "当前贴吧版本不受支持。请使用受支持的贴吧版本(%s-%s)或尝试更新模块。", "exception_init_preference" to "初始化设置失败,请尝试更换贴吧版本。", "regex_hint" to "请输入正则表达式,如.*", ) diff --git a/app/src/main/java/gm/tieba/tabswitch/XposedInit.java b/app/src/main/java/gm/tieba/tabswitch/XposedInit.java index 76d1ec4f..967f7e8c 100644 --- a/app/src/main/java/gm/tieba/tabswitch/XposedInit.java +++ b/app/src/main/java/gm/tieba/tabswitch/XposedInit.java @@ -10,7 +10,6 @@ import android.net.Uri; import android.os.Bundle; import android.text.TextUtils; -import android.view.WindowManager; import java.util.ArrayList; import java.util.Collection; @@ -60,7 +59,6 @@ import gm.tieba.tabswitch.hooker.extra.Hide; import gm.tieba.tabswitch.hooker.extra.StackTrace; import gm.tieba.tabswitch.util.DisplayUtils; -import gm.tieba.tabswitch.widget.TbDialog; import gm.tieba.tabswitch.widget.TbToast; public class XposedInit extends XposedContext implements IXposedHookZygoteInit, IXposedHookLoadPackage { @@ -160,7 +158,6 @@ protected void afterHookedMethod(MethodHookParam param) throws Throwable { new SelectClipboard() ); final var matchers = new ArrayList(hookers.size() + 2); - matchers.add(new TbDialog()); matchers.add(new TbToast()); for (final var hooker : hookers) { if (hooker instanceof Obfuscated) { @@ -241,7 +238,7 @@ protected void beforeHookedMethod(final MethodHookParam param) throws Throwable XposedBridge.log(message); AlertDialog alert = new AlertDialog.Builder(activity, DisplayUtils.isLightMode(getContext()) ? android.R.style.Theme_DeviceDefault_Light_Dialog_Alert : android.R.style.Theme_DeviceDefault_Dialog_Alert) - .setTitle("警告").setMessage(message).setCancelable(false) + .setTitle("规则异常").setMessage(message).setCancelable(false) .setNeutralButton("更新模块", (dialogInterface, i) -> { final Intent intent = new Intent(); intent.setAction("android.intent.action.VIEW"); @@ -254,10 +251,7 @@ protected void beforeHookedMethod(final MethodHookParam param) throws Throwable DeobfuscationHelper.saveAndRestart(activity, "unknown", null); }).create(); alert.show(); - WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(); - layoutParams.copyFrom(alert.getWindow().getAttributes()); - layoutParams.width = DisplayUtils.getDisplayWidth(getContext()); - alert.getWindow().setAttributes(layoutParams); + DisplayUtils.fixAlertDialogWidth(alert); } }); return; diff --git a/app/src/main/java/gm/tieba/tabswitch/hooker/TSPreference.java b/app/src/main/java/gm/tieba/tabswitch/hooker/TSPreference.java index 21b96614..dd0d4923 100644 --- a/app/src/main/java/gm/tieba/tabswitch/hooker/TSPreference.java +++ b/app/src/main/java/gm/tieba/tabswitch/hooker/TSPreference.java @@ -20,7 +20,6 @@ import org.jetbrains.annotations.NotNull; -import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.Locale; @@ -40,7 +39,6 @@ import gm.tieba.tabswitch.hooker.extra.TraceChecker; import gm.tieba.tabswitch.util.DisplayUtils; import gm.tieba.tabswitch.widget.NavigationBar; -import gm.tieba.tabswitch.widget.TbDialog; import gm.tieba.tabswitch.widget.TbToast; public class TSPreference extends XposedContext implements IHooker, Obfuscated { @@ -115,15 +113,18 @@ protected void afterHookedMethod(final MethodHookParam param) throws Throwable { } catch (final Throwable tr) { final var messages = new ArrayList(); messages.add(Constants.getStrings().get("exception_init_preference")); - messages.add(String.format(Locale.CHINA, "tbversion: %s, module version: %d", + messages.add(String.format(Locale.CHINA, "贴吧版本:%s, 模块版本:%d", DeobfuscationHelper.getTbVersion(getContext()), BuildConfig.VERSION_CODE)); messages.add(Log.getStackTraceString(tr)); final var message = TextUtils.join("\n", messages); XposedBridge.log(message); - new AlertDialog.Builder(activity, AlertDialog.THEME_DEVICE_DEFAULT_LIGHT) - .setTitle("警告").setMessage(message).setCancelable(false) + AlertDialog alert = new AlertDialog.Builder(activity, DisplayUtils.isLightMode(getContext()) ? + android.R.style.Theme_DeviceDefault_Light_Dialog_Alert : android.R.style.Theme_DeviceDefault_Dialog_Alert) + .setTitle("规则异常").setMessage(message).setCancelable(false) .setPositiveButton(activity.getString(android.R.string.ok), (dialogInterface, i) -> activity.finish()) - .show(); + .create(); + alert.show(); + DisplayUtils.fixAlertDialogWidth(alert); } } }); @@ -154,21 +155,17 @@ private void startRootPreferenceActivity(final Activity activity) { if (BuildConfig.VERSION_NAME.contains("alpha") || BuildConfig.VERSION_NAME.contains("beta")) { stringBuilder.append("\n\n").append(Constants.getStrings().get("dev_tip")); } - final TbDialog bdAlert = new TbDialog(activity, "使用协议", stringBuilder.toString(), true, null); - bdAlert.setOnNoButtonClickListener(v -> { - final Intent intent = new Intent(); - intent.setAction(Intent.ACTION_DELETE); - intent.setData(Uri.parse("package:" + (sPath.contains(BuildConfig.APPLICATION_ID) - && new File(sPath).exists() ? - BuildConfig.APPLICATION_ID : activity.getPackageName()))); - activity.startActivity(intent); - }); - bdAlert.setOnYesButtonClickListener(v -> { - Preferences.putEULAAccepted(); - startRootPreferenceActivity(activity); - bdAlert.dismiss(); - }); - bdAlert.show(); + AlertDialog alert = new AlertDialog.Builder(activity, DisplayUtils.isLightMode(getContext()) ? + android.R.style.Theme_DeviceDefault_Light_Dialog_Alert : android.R.style.Theme_DeviceDefault_Dialog_Alert) + .setTitle("使用协议").setMessage(stringBuilder.toString()) + .setNegativeButton(activity.getString(android.R.string.cancel), null) + .setPositiveButton(activity.getString(android.R.string.ok), (dialogInterface, i) -> { + Preferences.putEULAAccepted(); + startRootPreferenceActivity(activity); + }) + .create(); + alert.show(); + DisplayUtils.fixAlertDialogWidth(alert); } else { final Intent intent = new Intent().setClassName(activity, PROXY_ACTIVITY); intent.putExtra("proxyPage", MAIN); @@ -209,15 +206,17 @@ private LinearLayout createRootPreference(final Activity activity) { final SwitchButtonHolder autoSign = new SwitchButtonHolder(activity, "自动签到", "auto_sign", SwitchButtonHolder.TYPE_SWITCH); autoSign.setOnButtonClickListener(v -> { if (!Preferences.getIsAutoSignEnabled()) { - final TbDialog bdalert = new TbDialog(activity, "提示", - "这是一个需要网络请求并且有封号风险的功能,您需要自行承担使用此功能的风险,请谨慎使用!", true, null); - bdalert.setOnNoButtonClickListener(v2 -> bdalert.dismiss()); - bdalert.setOnYesButtonClickListener(v2 -> { - Preferences.putAutoSignEnabled(); - autoSign.bdSwitch.turnOn(); - bdalert.dismiss(); - }); - bdalert.show(); + AlertDialog alert = new AlertDialog.Builder(activity, DisplayUtils.isLightMode(getContext()) ? + android.R.style.Theme_DeviceDefault_Light_Dialog_Alert : android.R.style.Theme_DeviceDefault_Dialog_Alert) + .setTitle("提示").setMessage("这是一个需要网络请求并且有封号风险的功能,您需要自行承担使用此功能的风险,请谨慎使用!") + .setNegativeButton(activity.getString(android.R.string.cancel), null) + .setPositiveButton(activity.getString(android.R.string.ok), (dialogInterface, i) -> { + Preferences.putAutoSignEnabled(); + autoSign.bdSwitch.turnOn(); + }) + .create(); + alert.show(); + DisplayUtils.fixAlertDialogWidth(alert); } else { autoSign.bdSwitch.changeState(); } diff --git a/app/src/main/java/gm/tieba/tabswitch/hooker/TSPreferenceHelper.java b/app/src/main/java/gm/tieba/tabswitch/hooker/TSPreferenceHelper.java index 3f0f5f48..a45aaaa5 100644 --- a/app/src/main/java/gm/tieba/tabswitch/hooker/TSPreferenceHelper.java +++ b/app/src/main/java/gm/tieba/tabswitch/hooker/TSPreferenceHelper.java @@ -2,16 +2,20 @@ import android.annotation.SuppressLint; import android.app.Activity; +import android.app.AlertDialog; import android.content.Context; import android.graphics.Color; +import android.text.InputType; import android.text.TextUtils; import android.util.Log; +import android.view.Gravity; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.view.inputmethod.EditorInfo; +import android.widget.Button; import android.widget.EditText; import android.widget.ImageView; import android.widget.LinearLayout; @@ -32,10 +36,9 @@ import gm.tieba.tabswitch.Constants; import gm.tieba.tabswitch.XposedContext; import gm.tieba.tabswitch.dao.Preferences; +import gm.tieba.tabswitch.util.DisplayUtils; import gm.tieba.tabswitch.util.ReflectUtils; import gm.tieba.tabswitch.widget.Switch; -import gm.tieba.tabswitch.widget.TbDialog; -import gm.tieba.tabswitch.widget.TbEditText; import gm.tieba.tabswitch.widget.TbToast; public class TSPreferenceHelper extends XposedContext { @@ -190,7 +193,7 @@ static class SwitchButtonHolder { else bdSwitch.turnOff(); break; case TYPE_DIALOG: - switchButton = createButton(text, null, false, v -> showRegexDialog(activity)); + switchButton = createButton(text, null, false, v -> showRegexDialog(activity, text)); bdSwitchView.setOnTouchListener((v, event) -> false); if (Preferences.getString(key) != null) bdSwitch.turnOn(); else bdSwitch.turnOff(); @@ -207,34 +210,65 @@ void setOnButtonClickListener(final View.OnClickListener l) { }); } - private void showRegexDialog(final Activity activity) { - final EditText editText = new TbEditText(getContext()); + private void showRegexDialog(final Activity activity, final String title) { + Activity currentActivity = ReflectUtils.getCurrentActivity(); + boolean isLightMode = DisplayUtils.isLightMode(getContext()); + + final EditText editText = new EditText(currentActivity); editText.setHint(Constants.getStrings().get("regex_hint")); editText.setText(Preferences.getString(mKey)); - final TbDialog bdAlert = new TbDialog(activity, null, null, true, editText); - bdAlert.setOnNoButtonClickListener(v -> bdAlert.dismiss()); - bdAlert.setOnYesButtonClickListener(v -> { - try { - if (TextUtils.isEmpty(editText.getText())) { - Preferences.remove(mKey); - bdSwitch.turnOff(); - } else { - Pattern.compile(editText.getText().toString()); - Preferences.putString(mKey, editText.getText().toString()); - bdSwitch.turnOn(); + if (!isLightMode) { + editText.setTextColor(Color.WHITE); + editText.setHintTextColor(Color.GRAY); + } + editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE); + + final LinearLayout linearLayout = new LinearLayout(currentActivity); + linearLayout.setGravity(Gravity.CENTER_HORIZONTAL); + + LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT + ); + layoutParams.leftMargin = DisplayUtils.dipToPx(currentActivity, 20F); + layoutParams.rightMargin = DisplayUtils.dipToPx(currentActivity, 20F); + editText.setLayoutParams(layoutParams); + + linearLayout.addView(editText); + + AlertDialog alert = new AlertDialog.Builder(currentActivity, isLightMode ? + android.R.style.Theme_DeviceDefault_Light_Dialog_Alert : android.R.style.Theme_DeviceDefault_Dialog_Alert) + .setTitle(title).setView(linearLayout) + .setNegativeButton(activity.getString(android.R.string.cancel), null) + .setPositiveButton(activity.getString(android.R.string.ok), null).create(); + + alert.setOnShowListener(dialogInterface -> { + Button button = alert.getButton(AlertDialog.BUTTON_POSITIVE); + button.setOnClickListener(view -> { + try { + if (TextUtils.isEmpty(editText.getText())) { + Preferences.remove(mKey); + bdSwitch.turnOff(); + } else { + Pattern.compile(editText.getText().toString()); + Preferences.putString(mKey, editText.getText().toString()); + bdSwitch.turnOn(); + } + alert.dismiss(); + } catch (final PatternSyntaxException e) { + TbToast.showTbToast(e.getMessage(), TbToast.LENGTH_SHORT); } - bdAlert.dismiss(); - } catch (final PatternSyntaxException e) { - TbToast.showTbToast(e.getMessage(), TbToast.LENGTH_SHORT); - } + }); }); - bdAlert.show(); - bdAlert.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE); + + alert.show(); + DisplayUtils.fixAlertDialogWidth(alert); + + alert.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE); editText.setImeOptions(EditorInfo.IME_ACTION_DONE); editText.setOnEditorActionListener((v, actionId, event) -> { if (actionId == EditorInfo.IME_ACTION_DONE || event != null && event.getKeyCode() == KeyEvent.KEYCODE_ENTER) { - bdAlert.findYesButton().performClick(); + alert.getButton(AlertDialog.BUTTON_POSITIVE).performClick(); return true; } return false; diff --git a/app/src/main/java/gm/tieba/tabswitch/hooker/add/HistoryCache.java b/app/src/main/java/gm/tieba/tabswitch/hooker/add/HistoryCache.java index adff20fc..9cb525cd 100644 --- a/app/src/main/java/gm/tieba/tabswitch/hooker/add/HistoryCache.java +++ b/app/src/main/java/gm/tieba/tabswitch/hooker/add/HistoryCache.java @@ -1,13 +1,19 @@ package gm.tieba.tabswitch.hooker.add; import android.app.Activity; +import android.app.AlertDialog; +import android.graphics.Color; import android.os.Bundle; import android.text.Editable; +import android.text.InputType; import android.text.TextWatcher; +import android.view.Gravity; import android.view.KeyEvent; import android.view.WindowManager; import android.view.inputmethod.EditorInfo; +import android.widget.Button; import android.widget.EditText; +import android.widget.LinearLayout; import androidx.annotation.NonNull; @@ -21,10 +27,9 @@ import gm.tieba.tabswitch.Constants; import gm.tieba.tabswitch.XposedContext; import gm.tieba.tabswitch.hooker.IHooker; +import gm.tieba.tabswitch.util.DisplayUtils; import gm.tieba.tabswitch.util.ReflectUtils; import gm.tieba.tabswitch.widget.NavigationBar; -import gm.tieba.tabswitch.widget.TbDialog; -import gm.tieba.tabswitch.widget.TbEditText; import gm.tieba.tabswitch.widget.TbToast; public class HistoryCache extends XposedContext implements IHooker { @@ -56,7 +61,7 @@ protected void beforeHookedMethod(final MethodHookParam param) throws Throwable final var list = (List) param.args[0]; if (list == null) return; - final var pattern = Pattern.compile(mRegex); + final var pattern = Pattern.compile(mRegex, Pattern.CASE_INSENSITIVE); list.removeIf(o -> { String[] strings; try { @@ -78,9 +83,18 @@ protected void beforeHookedMethod(final MethodHookParam param) throws Throwable } private void showRegexDialog(final Activity activity) { - final EditText editText = new TbEditText(activity); + Activity currentActivity = ReflectUtils.getCurrentActivity(); + boolean isLightMode = DisplayUtils.isLightMode(getContext()); + + final EditText editText = new EditText(currentActivity); editText.setHint(Constants.getStrings().get("regex_hint")); editText.setText(mRegex); + if (!isLightMode) { + editText.setTextColor(Color.WHITE); + editText.setHintTextColor(Color.GRAY); + } + editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE); + editText.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(final CharSequence s, final int start, final int count, final int after) { @@ -95,25 +109,48 @@ public void afterTextChanged(final Editable s) { mRegex = s.toString(); } }); - final TbDialog bdAlert = new TbDialog(activity, null, null, true, editText); - bdAlert.setOnNoButtonClickListener(v -> bdAlert.dismiss()); - bdAlert.setOnYesButtonClickListener(v -> { - try { - Pattern.compile(editText.getText().toString()); - bdAlert.dismiss(); - activity.recreate(); - } catch (final PatternSyntaxException e) { - TbToast.showTbToast(e.getMessage(), TbToast.LENGTH_SHORT); - } + + final LinearLayout linearLayout = new LinearLayout(currentActivity); + linearLayout.setGravity(Gravity.CENTER_HORIZONTAL); + + LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT + ); + layoutParams.leftMargin = DisplayUtils.dipToPx(currentActivity, 20F); + layoutParams.rightMargin = DisplayUtils.dipToPx(currentActivity, 20F); + editText.setLayoutParams(layoutParams); + + linearLayout.addView(editText); + + AlertDialog alert = new AlertDialog.Builder(currentActivity, isLightMode ? + android.R.style.Theme_DeviceDefault_Light_Dialog_Alert : android.R.style.Theme_DeviceDefault_Dialog_Alert) + .setTitle("搜索").setView(linearLayout) + .setNegativeButton(activity.getString(android.R.string.cancel), null) + .setPositiveButton(activity.getString(android.R.string.ok), null).create(); + + alert.setOnShowListener(dialogInterface -> { + Button button = alert.getButton(AlertDialog.BUTTON_POSITIVE); + button.setOnClickListener(view -> { + try { + Pattern.compile(editText.getText().toString()); + alert.dismiss(); + activity.recreate(); + } catch (final PatternSyntaxException e) { + TbToast.showTbToast(e.getMessage(), TbToast.LENGTH_SHORT); + } + }); }); - bdAlert.show(); - bdAlert.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE); + + alert.show(); + DisplayUtils.fixAlertDialogWidth(alert); + + alert.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE); editText.setSingleLine(); editText.setImeOptions(EditorInfo.IME_ACTION_SEARCH); editText.setOnEditorActionListener((v, actionId, event) -> { if (actionId == EditorInfo.IME_ACTION_SEARCH || event != null && event.getKeyCode() == KeyEvent.KEYCODE_ENTER) { - bdAlert.findYesButton().performClick(); + alert.getButton(AlertDialog.BUTTON_POSITIVE).performClick(); return true; } return false; diff --git a/app/src/main/java/gm/tieba/tabswitch/hooker/add/SelectClipboard.java b/app/src/main/java/gm/tieba/tabswitch/hooker/add/SelectClipboard.java index 6f4a6dc0..df150ca9 100644 --- a/app/src/main/java/gm/tieba/tabswitch/hooker/add/SelectClipboard.java +++ b/app/src/main/java/gm/tieba/tabswitch/hooker/add/SelectClipboard.java @@ -5,7 +5,6 @@ import android.content.ClipboardManager; import android.content.Context; import android.view.View; -import android.view.WindowManager; import android.widget.TextView; import androidx.annotation.NonNull; @@ -65,11 +64,7 @@ protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { ((TextView) messageView).setTextIsSelectable(true); } - WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(); - layoutParams.copyFrom(alert.getWindow().getAttributes()); - layoutParams.width = DisplayUtils.getDisplayWidth(getContext()); - alert.getWindow().setAttributes(layoutParams); - + DisplayUtils.fixAlertDialogWidth(alert); return null; } }); diff --git a/app/src/main/java/gm/tieba/tabswitch/hooker/eliminate/RegexFilter.java b/app/src/main/java/gm/tieba/tabswitch/hooker/eliminate/RegexFilter.java index 45d4d191..15d328fc 100644 --- a/app/src/main/java/gm/tieba/tabswitch/hooker/eliminate/RegexFilter.java +++ b/app/src/main/java/gm/tieba/tabswitch/hooker/eliminate/RegexFilter.java @@ -17,7 +17,7 @@ default Pattern getPattern() { final var _regex = Preferences.getString(key()); if (!_regex.equals(regex[0])) { regex[0] = _regex; - pattern[0] = Pattern.compile(_regex); + pattern[0] = Pattern.compile(_regex, Pattern.CASE_INSENSITIVE); } return pattern[0]; } diff --git a/app/src/main/java/gm/tieba/tabswitch/util/DisplayUtils.java b/app/src/main/java/gm/tieba/tabswitch/util/DisplayUtils.java index 8b84025e..0abf5afa 100644 --- a/app/src/main/java/gm/tieba/tabswitch/util/DisplayUtils.java +++ b/app/src/main/java/gm/tieba/tabswitch/util/DisplayUtils.java @@ -1,9 +1,11 @@ package gm.tieba.tabswitch.util; import android.app.Activity; +import android.app.AlertDialog; import android.content.Context; import android.content.Intent; import android.content.res.Configuration; +import android.view.WindowManager; import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.XposedHelpers; @@ -65,4 +67,11 @@ public static int pxToDip(final Context context, final float pxValue) { public static int getDisplayWidth(final Context context) { return context.getResources().getDisplayMetrics().widthPixels; } + + public static void fixAlertDialogWidth(AlertDialog alert) { + WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(); + layoutParams.copyFrom(alert.getWindow().getAttributes()); + layoutParams.width = DisplayUtils.getDisplayWidth(getContext()); + alert.getWindow().setAttributes(layoutParams); + } } diff --git a/app/src/main/java/gm/tieba/tabswitch/util/Parser.java b/app/src/main/java/gm/tieba/tabswitch/util/Parser.java index 0abad942..13f23034 100644 --- a/app/src/main/java/gm/tieba/tabswitch/util/Parser.java +++ b/app/src/main/java/gm/tieba/tabswitch/util/Parser.java @@ -1,6 +1,7 @@ package gm.tieba.tabswitch.util; import java.util.List; +import java.util.Locale; import de.robv.android.xposed.XposedHelpers; import gm.tieba.tabswitch.XposedContext; @@ -12,6 +13,6 @@ public static String parsePbContent(final Object instance, final String fieldNam for (int i = 0; i < contents.size(); i++) { pbContent.append(XposedHelpers.getObjectField(contents.get(i), "text")); } - return pbContent.toString(); + return pbContent.toString().toLowerCase(Locale.CHINA); } } diff --git a/app/src/main/java/gm/tieba/tabswitch/widget/TbDialog.java b/app/src/main/java/gm/tieba/tabswitch/widget/TbDialog.java deleted file mode 100644 index bf52eba8..00000000 --- a/app/src/main/java/gm/tieba/tabswitch/widget/TbDialog.java +++ /dev/null @@ -1,167 +0,0 @@ -package gm.tieba.tabswitch.widget; - -import android.app.Activity; -import android.view.View; -import android.view.Window; -import android.widget.TextView; - -import java.util.Arrays; -import java.util.List; -import java.util.function.Consumer; - -import de.robv.android.xposed.XC_MethodHook; -import de.robv.android.xposed.XposedHelpers; -import gm.tieba.tabswitch.XposedContext; -import gm.tieba.tabswitch.dao.AcRules; -import gm.tieba.tabswitch.hooker.Obfuscated; -import gm.tieba.tabswitch.hooker.deobfuscation.Matcher; -import gm.tieba.tabswitch.hooker.deobfuscation.StringMatcher; -import gm.tieba.tabswitch.util.ReflectUtils; - -public class TbDialog extends XposedContext implements Obfuscated { - private Class mClass; - private Object mBdAlert; - private Object mPageContext; - private Object mDialog; - - @Override - public List matchers() { - return List.of(new StringMatcher("Dialog must be created by function create()!")); - } - - public TbDialog() { - } - - public TbDialog(final Activity activity, final String title, final String message, final boolean cancelable, final View contentView) { - XposedHelpers.findAndHookMethod("com.baidu.tbadk.core.BaseFragment", sClassLoader, - "getPageContext", new XC_MethodHook() { - @Override - protected void afterHookedMethod(final MethodHookParam param) throws Throwable { - mPageContext = param.getResult(); - } - }); - AcRules.findRule(matchers(), (matcher, clazz, method) -> { - final var cls = XposedHelpers.findClass(clazz, sClassLoader); - if (cls.getDeclaredMethods().length < 20) { - return; - } - mClass = cls; - mBdAlert = XposedHelpers.newInstance(mClass, activity); - try { - XposedHelpers.setObjectField(mBdAlert, "mTitle", title); - XposedHelpers.setObjectField(mBdAlert, "mMessage", message); - XposedHelpers.setObjectField(mBdAlert, "mCancelable", cancelable); - XposedHelpers.setObjectField(mBdAlert, "mContentView", contentView); - } catch (final NoSuchFieldError e) { - XposedHelpers.setObjectField(mBdAlert, "f", title); - XposedHelpers.setObjectField(mBdAlert, "h", message); - XposedHelpers.setObjectField(mBdAlert, "C", cancelable); - XposedHelpers.setObjectField(mBdAlert, "g", contentView); - } - - initButtonStyle(param -> { - final int color = ReflectUtils.getColor("CAM_X0204"); - // R.id.bdDialog_divider_line - final var bdDialogDividerLine = (View) XposedHelpers.getObjectField(mBdAlert, "bdDialog_divider_line"); - if (bdDialogDividerLine != null) { - bdDialogDividerLine.setBackgroundColor(color); - } - // R.id.divider_yes_no_button - final var dividerWithButton = (View) XposedHelpers.getObjectField(mBdAlert, "dividerWithButton"); - if (dividerWithButton != null) { - dividerWithButton.setBackgroundColor(color); - } - }); - }); - } - - // called in create() - private void initButtonStyle(final Consumer consumer) { - XposedHelpers.findAndHookMethod(mClass, "initButtonStyle", new XC_MethodHook() { - @Override - protected void beforeHookedMethod(final MethodHookParam param) throws Throwable { - consumer.accept(param); - } - }); - } - - public void setOnNoButtonClickListener(final View.OnClickListener l) { - initButtonStyle(param -> { - final var cancel = getContext().getString(android.R.string.cancel); - try { - XposedHelpers.setObjectField(mBdAlert, "mNegativeButtonTip", cancel); - } catch (final NoSuchFieldError e) { - XposedHelpers.setObjectField(mBdAlert, "m", cancel); - } - // R.id.no - final var noButton = (TextView) XposedHelpers.getObjectField(mBdAlert, "noButton"); - if (noButton != null) { - noButton.setOnClickListener(l); - } - }); - } - - public void setOnYesButtonClickListener(final View.OnClickListener l) { - initButtonStyle(param -> { - final var ok = getContext().getString(android.R.string.ok); - try { - XposedHelpers.setObjectField(mBdAlert, "mPositiveButtonTip", ok); - } catch (final NoSuchFieldError e) { - XposedHelpers.setObjectField(mBdAlert, "l", ok); - } - final var yesButton = (TextView) findYesButton(); - if (yesButton != null) { - yesButton.setOnClickListener(l); - } - }); - } - - public TextView findYesButton() { - // R.id.yes - return (TextView) XposedHelpers.getObjectField(mBdAlert, "yesButton"); - } - - public void show() { - for (final var md : mClass.getDeclaredMethods()) { - final var parameterTypesString = Arrays.toString(md.getParameterTypes()); - if (parameterTypesString.startsWith("[interface") && - !parameterTypesString.contains("$")) { - ReflectUtils.callMethod(md, mBdAlert, mPageContext); // create() - } - } -// LinearLayout parent = mRootView.findViewById(ReflectUtils.getId("dialog_content")); -// if (parent.getChildAt(0) instanceof LinearLayout) { -// LinearLayout linearLayout = (LinearLayout) parent.getChildAt(0); -// for (int i = 0, childCount = linearLayout.getChildCount(); i < childCount; i++) { -// View view = linearLayout.getChildAt(i); -// if (view instanceof TextView) { -// ((TextView) view).setTextColor(ReflectUtils.getColor("CAM_X0105")); -// } -// } -// } - for (final var method : mClass.getDeclaredMethods()) { - if (method.getParameterTypes().length == 0 && mClass.equals(method.getReturnType())) { - ReflectUtils.callMethod(method, mBdAlert); // show() - break; - } - } - try { - mDialog = XposedHelpers.getObjectField(mBdAlert, "mDialog"); - } catch (final NoSuchFieldError e) { - mDialog = XposedHelpers.getObjectField(mBdAlert, "w"); - } - } - - public Window getWindow() { - if (mDialog == null) throw new IllegalStateException("you must call show before getWindow"); - else return (Window) XposedHelpers.callMethod(mDialog, "getWindow"); - } - - public void dismiss() { - try { - XposedHelpers.callMethod(mBdAlert, "dismiss"); - } catch (final NoSuchMethodError e) { - XposedHelpers.callMethod(mBdAlert, "k"); - } - } -}