From 140870b5ec9785475d248de257923ab30b24a21e Mon Sep 17 00:00:00 2001 From: SuperMonster003 Date: Wed, 4 Feb 2026 13:36:49 +0800 Subject: [PATCH] 6.7.0 - Alpha19 - Fine tuning --- .../java/org/autojs/autojs/app/DialogUtils.kt | 109 ++++++++++-------- .../autojs/app/tool/JsonSocketClientTool.kt | 2 + .../plugin/center/PluginCenterActivity.kt | 3 + .../autojs/engine/ScriptEngineService.java | 29 ++++- .../ScriptExecutionGlobalListener.java | 35 ------ .../DisplayVersionHistoriesActivity.kt | 2 + .../ui/settings/WorkingDirectoryPreference.kt | 3 + .../org/autojs/autojs/util/IntentUtils.kt | 2 + .../org/autojs/autojs/util/UpdateUtils.kt | 2 + 9 files changed, 101 insertions(+), 86 deletions(-) diff --git a/app/src/main/java/org/autojs/autojs/app/DialogUtils.kt b/app/src/main/java/org/autojs/autojs/app/DialogUtils.kt index fb3928e8..b65bf11c 100644 --- a/app/src/main/java/org/autojs/autojs/app/DialogUtils.kt +++ b/app/src/main/java/org/autojs/autojs/app/DialogUtils.kt @@ -39,18 +39,21 @@ import java.util.concurrent.atomic.AtomicReference * Transformed by SuperMonster003 on Oct 19, 2022. * Modified by OpenAI ChatGPT (GPT-5.2 Thinking) as of Jan 20, 2026. * Modified by JetBrains AI Assistant (GPT-5.2) as of Feb 1, 2026. - * Modified by SuperMonster003 as of Feb 1, 2026. + * Modified by SuperMonster003 as of Feb 3, 2026. */ object DialogUtils { private const val TAG = "DialogUtils" @JvmStatic - fun MaterialDialog.Builder.showAdaptive() = build().showAdaptive() + fun T.showAdaptive(): MaterialDialog = build().showAdaptive() + + @JvmStatic + fun T.showAdaptiveOrNull(): MaterialDialog? = build()?.showAdaptive() @JvmStatic @Suppress("DEPRECATION") - fun MaterialDialog.showAdaptive() = showDialog(this) + fun T.showAdaptive(): T = showDialog(this) /** * Show this [MaterialDialog] in a context-safe way. @@ -92,7 +95,7 @@ object DialogUtils { @JvmOverloads @Deprecated("Use showAdaptive instead.", ReplaceWith("showAdaptive(dialog, focusable)")) @ReservedForCompatibility - fun showDialog(dialog: MaterialDialog, focusable: Boolean = true): MaterialDialog { + fun showDialog(dialog: T, focusable: Boolean = true): T { runOnMain { // Prevent duplicated show. // zh-CN: 防止重复 show(). @@ -189,39 +192,18 @@ object DialogUtils { return dialog } - /** - * Build dialog on the main thread and return it. - * - * Note: - * - MaterialDialog.Builder.build() may internally create Android Dialog/Handler. - * - Building on a background thread can crash with "Can't create handler inside thread ...". - * - * zh-CN: - * - * 在主线程 build 对话框并返回实例. - * - * 注: - * - MaterialDialog.Builder.build() 内部可能创建 Android Dialog/Handler. - * - 在后台线程 build 可能触发 "Can't create handler inside thread ..." 崩溃. - */ - @JvmStatic - fun buildAdaptive(builder: MaterialDialog.Builder): MaterialDialog { - @Suppress("UNCHECKED_CAST") - return buildAdaptive { builder.build() } - } - /** * Build dialog on the main thread by a callable factory. * * zh-CN: 通过 callable 工厂在主线程 build 对话框. */ @JvmStatic - fun buildAdaptive(factory: Callable): MaterialDialog { + fun buildAdaptive(factory: Callable): T { if (Looper.getMainLooper() == Looper.myLooper()) { return factory.call() } - val ref = AtomicReference() + val ref = AtomicReference() val err = AtomicReference() val latch = CountDownLatch(1) @@ -245,21 +227,34 @@ object DialogUtils { return ref.get() ?: throw RuntimeException("buildAdaptive: dialog is null (timeout or build failed)") } - /** - * Build and show dialog on the main thread, then return the dialog instance. - * Use this when the caller might be running on a background thread. - * - * zh-CN: - * - * 在主线程 build 并 show 对话框, 然后返回对话框实例. - * 当调用方可能运行在后台线程时使用该方法. - */ @JvmStatic - @JvmOverloads - fun buildAndShowAdaptive(builder: MaterialDialog.Builder, focusable: Boolean = true): MaterialDialog { - val dialog = buildAdaptive(builder) - @Suppress("DEPRECATION") - return showDialog(dialog, focusable) + fun buildAdaptiveOrNull(factory: Callable): T? { + if (Looper.getMainLooper() == Looper.myLooper()) { + return factory.call() + } + + val ref = AtomicReference() + val err = AtomicReference() + val latch = CountDownLatch(1) + + GlobalAppContext.post { + try { + ref.set(factory.call()) + } catch (t: Throwable) { + err.set(t) + Log.w(TAG, "buildAdaptiveOrNull: failed", t) + } finally { + latch.countDown() + } + } + + // Wait a bit to avoid infinite blocking in background threads. + // zh-CN: 设置等待超时以避免后台线程无限阻塞. + latch.await(5, TimeUnit.SECONDS) + + err.get()?.let { throw RuntimeException(it) } + + return ref.get() } /** @@ -268,10 +263,32 @@ object DialogUtils { * zh-CN: 使用 callable 工厂在主线程 build 并 show 对话框, 然后返回实例. */ @JvmStatic - @JvmOverloads - fun buildAndShowAdaptive(factory: Callable, focusable: Boolean = true): MaterialDialog { + @Suppress("DEPRECATION") + fun buildAndShowAdaptive(factory: Callable): T { + return buildAndShowAdaptive(factory, true) + } + + /** + * Build and show dialog on the main thread with a callable factory, then return the instance. + * + * zh-CN: 使用 callable 工厂在主线程 build 并 show 对话框, 然后返回实例. + */ + @JvmStatic + @Suppress("DEPRECATION") + fun buildAndShowAdaptive(factory: Callable, focusable: Boolean): T { val dialog = buildAdaptive(factory) - @Suppress("DEPRECATION") + return showDialog(dialog, focusable) + } + + @JvmStatic + @Suppress("DEPRECATION") + fun buildAndShowAdaptiveOrNull(factory: Callable): T? = + buildAndShowAdaptiveOrNull(factory, true) + + @JvmStatic + @Suppress("DEPRECATION") + fun buildAndShowAdaptiveOrNull(factory: Callable, focusable: Boolean): T? { + val dialog = buildAdaptiveOrNull(factory) ?: return null return showDialog(dialog, focusable) } @@ -468,8 +485,8 @@ object DialogUtils { fun MaterialDialog.applyProgressThemeColorTintLists(): MaterialDialog = also { val progressBar = progressBar ?: return@also - val bgColor = context.getColor(R.color.dialog_progress_gray_background_tint) - val fgColor = ColorUtils.adjustColorForContrast(bgColor, ThemeColorManager.colorPrimary, 2.3) + val fgColor = ColorUtils.adjustColorForContrast(context.getColor(R.color.dialog_progress_gray_background_tint), ThemeColorManager.colorPrimary, 2.3) + val bgColor = ColorUtils.applyAlpha(fgColor, 0.2) progressBar.setProgressTintList(ColorStateList.valueOf(fgColor)) progressBar.setProgressBackgroundTintList(ColorStateList.valueOf(bgColor)) diff --git a/app/src/main/java/org/autojs/autojs/app/tool/JsonSocketClientTool.kt b/app/src/main/java/org/autojs/autojs/app/tool/JsonSocketClientTool.kt index 03e94ccc..2b94c5a7 100644 --- a/app/src/main/java/org/autojs/autojs/app/tool/JsonSocketClientTool.kt +++ b/app/src/main/java/org/autojs/autojs/app/tool/JsonSocketClientTool.kt @@ -19,6 +19,7 @@ import org.autojs.autojs.util.MaterialDialogUtils.widgetThemeColor import org.autojs.autojs.pluginclient.DevPluginService import org.autojs.autojs.pluginclient.JsonSocketClient import org.autojs.autojs.ui.common.NotAskAgainDialog +import org.autojs.autojs.util.MaterialDialogUtils.choiceWidgetThemeColor import org.autojs.autojs.util.Observers import org.autojs.autojs.util.ThreadUtils.runOnMain import org.autojs.autojs.util.ViewUtils @@ -229,6 +230,7 @@ class JsonSocketClientTool(context: Context) : AbstractJsonSocketTool(context) { dialog.inputEditText?.setText(text) validateAndConnectToRemoteServer(dialog) } + .choiceWidgetThemeColor() .itemsLongCallback { dHistories, _, _, text -> MaterialDialog.Builder(context) .title(R.string.text_prompt) diff --git a/app/src/main/java/org/autojs/autojs/core/plugin/center/PluginCenterActivity.kt b/app/src/main/java/org/autojs/autojs/core/plugin/center/PluginCenterActivity.kt index 1256eece..99800c03 100644 --- a/app/src/main/java/org/autojs/autojs/core/plugin/center/PluginCenterActivity.kt +++ b/app/src/main/java/org/autojs/autojs/core/plugin/center/PluginCenterActivity.kt @@ -14,6 +14,7 @@ import kotlinx.coroutines.launch import org.autojs.autojs.ui.BaseActivity import org.autojs.autojs.ui.widget.SearchViewItem import org.autojs.autojs.util.IntentUtils.startSafely +import org.autojs.autojs.util.MaterialDialogUtils.choiceWidgetThemeColor import org.autojs.autojs.util.ViewUtils import org.autojs.autojs.util.ViewUtils.onceGlobalLayout import org.autojs.autojs.util.ViewUtils.setMenuIconsColorByThemeColorLuminance @@ -135,6 +136,7 @@ class PluginCenterActivity : BaseActivity() { else -> Unit } } + .choiceWidgetThemeColor() .negativeText(R.string.text_cancel) .negativeColorRes(R.color.dialog_button_default) .show() @@ -167,6 +169,7 @@ class PluginCenterActivity : BaseActivity() { else -> Unit } } + .choiceWidgetThemeColor() .negativeText(R.string.text_cancel) .negativeColorRes(R.color.dialog_button_default) .show() diff --git a/app/src/main/java/org/autojs/autojs/engine/ScriptEngineService.java b/app/src/main/java/org/autojs/autojs/engine/ScriptEngineService.java index 7779254c..1c636fce 100644 --- a/app/src/main/java/org/autojs/autojs/engine/ScriptEngineService.java +++ b/app/src/main/java/org/autojs/autojs/engine/ScriptEngineService.java @@ -17,6 +17,7 @@ import org.autojs.autojs.execution.SimpleScriptExecutionListener; import org.autojs.autojs.lang.ThreadCompat; import org.autojs.autojs.runtime.ScriptRuntime; import org.autojs.autojs.runtime.api.Console; +import org.autojs.autojs.runtime.api.augment.engines.Engines; import org.autojs.autojs.runtime.exception.ScriptInterruptedException; import org.autojs.autojs.script.JavaScriptSource; import org.autojs.autojs.script.ScriptSource; @@ -66,6 +67,7 @@ public class ScriptEngineService { if (execution.getEngine() instanceof JavaScriptEngine) { ((JavaScriptEngine) execution.getEngine()).getRuntime().console.setTitle(scriptSource.getName()); } + emitEngineEvent("start", execution.getEngine()); mGlobalConsole.verbose(MessageFormat.format("{0} [{1}].", getLanguageContext().getString(R.string.text_start_running), scriptSource.getElegantPath())); } @@ -75,26 +77,34 @@ public class ScriptEngineService { } private void onFinish(ScriptExecution execution) { - /* Empty function body. */ + var engine = execution.getEngine(); + emitEngineEvent("finish", engine); + emitEngineEvent("exit", engine); + emitEngineEvent("stop", engine); } @Override public void onException(ScriptExecution execution, Throwable e) { Log.d(TAG, "onException"); e.printStackTrace(); + + var engine = execution.getEngine(); + emitEngineEvent("exception", engine, e); + emitEngineEvent("error", engine, e); + onFinish(execution); String message = null; if (!ScriptInterruptedException.causedByInterrupt(e)) { message = e.getMessage(); - if (execution.getEngine() instanceof JavaScriptEngine engine) { - engine.getRuntime().console.error(e); + if (engine instanceof JavaScriptEngine scriptEngine) { + scriptEngine.getRuntime().console.error(e); } } - if (execution.getEngine() instanceof JavaScriptEngine engine) { + if (engine instanceof JavaScriptEngine scriptEngine) { Throwable uncaughtException = engine.getUncaughtException(); if (uncaughtException != null) { message = uncaughtException.getMessage(); - engine.getRuntime().console.error(uncaughtException); + scriptEngine.getRuntime().console.error(uncaughtException); } } if (message != null) { @@ -211,6 +221,15 @@ public class ScriptEngineService { return mScriptExecutions.get(id); } + private void emitEngineEvent(String eventName, ScriptEngine engine, Object... args) { + for (ScriptEngine scriptEngine : getEngines()) { + if (scriptEngine instanceof JavaScriptEngine jsEngine) { + ScriptRuntime runtime = jsEngine.getRuntime(); + Engines.emit(runtime, eventName, engine, args); + } + } + } + public static void setInstance(ScriptEngineService service) { if (sInstance != null) { throw new IllegalStateException(); diff --git a/app/src/main/java/org/autojs/autojs/execution/ScriptExecutionGlobalListener.java b/app/src/main/java/org/autojs/autojs/execution/ScriptExecutionGlobalListener.java index 81f8604d..2eb72b44 100644 --- a/app/src/main/java/org/autojs/autojs/execution/ScriptExecutionGlobalListener.java +++ b/app/src/main/java/org/autojs/autojs/execution/ScriptExecutionGlobalListener.java @@ -2,17 +2,11 @@ package org.autojs.autojs.execution; import org.autojs.autojs.AutoJs; import org.autojs.autojs.core.pref.Language; -import org.autojs.autojs.engine.JavaScriptEngine; import org.autojs.autojs.engine.ScriptEngine; -import org.autojs.autojs.runtime.ScriptRuntime; import org.autojs.autojs.runtime.api.Console; -import org.autojs.autojs.runtime.api.augment.engines.Engines; import org.autojs.autojs.script.ScriptSource; import org.autojs.autojs6.R; -import java.util.List; -import java.util.stream.Collectors; - import static org.autojs.autojs.util.StringUtils.str; /** @@ -26,9 +20,6 @@ public class ScriptExecutionGlobalListener implements ScriptExecutionListener { @Override public void onStart(ScriptExecution execution) { ScriptEngine engine = execution.getEngine(); - - emitEngineEvent("start", engine); - engine.setTag(ENGINE_TAG_START_TIME, System.currentTimeMillis()); } @@ -39,11 +30,6 @@ public class ScriptExecutionGlobalListener implements ScriptExecutionListener { private void onFinish(ScriptExecution execution) { ScriptEngine engine = execution.getEngine(); - - emitEngineEvent("finish", engine); - emitEngineEvent("exit", engine); - emitEngineEvent("stop", engine); - Long startTime = (Long) engine.getTag(ENGINE_TAG_START_TIME); if (startTime != null) { printSeconds(execution, startTime); @@ -60,27 +46,6 @@ public class ScriptExecutionGlobalListener implements ScriptExecutionListener { @Override public void onException(ScriptExecution execution, Throwable e) { - ScriptEngine engine = execution.getEngine(); - - emitEngineEvent("exception", engine, e); - emitEngineEvent("error", engine, e); - onFinish(execution); } - - private void emitEngineEvent(String eventName, ScriptEngine engine, Object... args) { - List jsEngines = AutoJs.getInstance() - .getScriptEngineService() - .getEngines() - .stream() - .filter(JavaScriptEngine.class::isInstance) - .map(JavaScriptEngine.class::cast) - .collect(Collectors.toList()); - - for (JavaScriptEngine jsEngine : jsEngines) { - ScriptRuntime runtime = jsEngine.getRuntime(); - Engines.emit(runtime, eventName, engine, args); - } - } - } \ No newline at end of file diff --git a/app/src/main/java/org/autojs/autojs/ui/settings/DisplayVersionHistoriesActivity.kt b/app/src/main/java/org/autojs/autojs/ui/settings/DisplayVersionHistoriesActivity.kt index 460dc7f8..0898fa0f 100644 --- a/app/src/main/java/org/autojs/autojs/ui/settings/DisplayVersionHistoriesActivity.kt +++ b/app/src/main/java/org/autojs/autojs/ui/settings/DisplayVersionHistoriesActivity.kt @@ -35,6 +35,7 @@ import org.autojs.autojs.ui.settings.VersionHistoryRepository.Companion.Category import org.autojs.autojs.ui.settings.VersionHistoryRepository.Companion.DEFAULT_FILTER import org.autojs.autojs.ui.settings.VersionHistoryRepository.Companion.DEFAULT_VERSION_NAME import org.autojs.autojs.util.IntentUtils.startSafely +import org.autojs.autojs.util.MaterialDialogUtils.choiceWidgetThemeColor import org.autojs.autojs.util.ProcessLogger import org.autojs.autojs.util.ViewUtils.excludePaddingClippableViewFromBottomNavigationBar import org.autojs.autojs.util.ViewUtils.setMenuIconsColorByThemeColorLuminance @@ -208,6 +209,7 @@ class DisplayVersionHistoriesActivity : BaseActivity() { } true } + .choiceWidgetThemeColor() .show() } diff --git a/app/src/main/java/org/autojs/autojs/ui/settings/WorkingDirectoryPreference.kt b/app/src/main/java/org/autojs/autojs/ui/settings/WorkingDirectoryPreference.kt index ac15f9eb..ddeb5cb3 100644 --- a/app/src/main/java/org/autojs/autojs/ui/settings/WorkingDirectoryPreference.kt +++ b/app/src/main/java/org/autojs/autojs/ui/settings/WorkingDirectoryPreference.kt @@ -25,6 +25,7 @@ import org.autojs.autojs.tool.SimpleObserver import org.autojs.autojs.ui.filechooser.FileChooserDialogBuilder import org.autojs.autojs.ui.main.MainActivity import org.autojs.autojs.util.EnvironmentUtils +import org.autojs.autojs.util.MaterialDialogUtils.choiceWidgetThemeColor import org.autojs.autojs.util.ViewUtils import org.autojs.autojs.util.WorkingDirectoryUtils import org.autojs.autojs6.R @@ -82,6 +83,7 @@ class WorkingDirectoryPreference : MaterialPreference { .itemsCallback { _, _, _, text -> mContentView.setText(text) } + .choiceWidgetThemeColor() .negativeText(R.string.dialog_button_back) .showAdaptive() } @@ -128,6 +130,7 @@ class WorkingDirectoryPreference : MaterialPreference { .showAdaptive() } } + .choiceWidgetThemeColor() .negativeText(R.string.dialog_button_back) .negativeColorRes(R.color.dialog_button_default) .onNegative { dHistories, _ -> dHistories.dismiss() } diff --git a/app/src/main/java/org/autojs/autojs/util/IntentUtils.kt b/app/src/main/java/org/autojs/autojs/util/IntentUtils.kt index 6e95b50b..7f20969b 100644 --- a/app/src/main/java/org/autojs/autojs/util/IntentUtils.kt +++ b/app/src/main/java/org/autojs/autojs/util/IntentUtils.kt @@ -38,6 +38,7 @@ import org.autojs.autojs.runtime.api.WrappedShizuku import org.autojs.autojs.ui.enhancedfloaty.FloatyService import org.autojs.autojs.ui.floating.FloatyWindowManger import org.autojs.autojs.util.ContextUtils.findActivity +import org.autojs.autojs.util.MaterialDialogUtils.choiceWidgetThemeColor import org.autojs.autojs.util.StringUtils.key import org.autojs.autojs6.R import java.io.File @@ -551,6 +552,7 @@ object IntentUtils { .autoDismiss(false) .show() } + .choiceWidgetThemeColor() .positiveText(R.string.dialog_button_dismiss) .onPositive { dialog, _ -> dialog.dismiss() } .cancelable(false) diff --git a/app/src/main/java/org/autojs/autojs/util/UpdateUtils.kt b/app/src/main/java/org/autojs/autojs/util/UpdateUtils.kt index ea324b9d..600a48ed 100644 --- a/app/src/main/java/org/autojs/autojs/util/UpdateUtils.kt +++ b/app/src/main/java/org/autojs/autojs/util/UpdateUtils.kt @@ -14,6 +14,7 @@ import org.autojs.autojs.core.pref.Pref.lastUpdatesPostponedTimestamp import org.autojs.autojs.network.UpdateChecker import org.autojs.autojs.network.UpdateChecker.PromptMode import org.autojs.autojs.network.entity.VersionInfo +import org.autojs.autojs.util.MaterialDialogUtils.choiceWidgetThemeColor import org.autojs.autojs6.R /** @@ -67,6 +68,7 @@ object UpdateUtils { .autoDismiss(false) .show() } + .choiceWidgetThemeColor() .neutralText(R.string.dialog_button_clear_items) .neutralColorRes(R.color.dialog_button_warn) .onNeutral { dialogParent, _ ->