6.7.0 - Alpha18 - 修复 toast 方法因持有 Toast 实例强引用而导致可能得内存泄露问题
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$data": {
|
||||
"v6.7.0": {
|
||||
"released_date": "2026/01/29",
|
||||
"released_date": "2026/01/30",
|
||||
"feature": [
|
||||
"插件中心功能, 支持插件的安装/卸载/更新等操作 (入口: 主页抽屉按钮/主页标签页)",
|
||||
"Paddle OCR (PP-OCRv5) 插件, 用于光学字符识别",
|
||||
@@ -61,6 +61,7 @@
|
||||
"console.build 方法的 (title/content)BackgroundColor 选项导致透明度或着色选项被覆盖的问题 _[`issue #458`](http://issues.autojs6.com/458)_",
|
||||
"console/toast 等方法显示 Java Double 时可能丢失末尾零的问题",
|
||||
"无法使用 console/toast 等方法显示 BigInt 数据类型的问题",
|
||||
"toast 方法因持有 Toast 实例强引用而导致可能得内存泄露问题",
|
||||
"部分全局对象可能丢失 JavaScript 原型属性及方法的问题",
|
||||
"使用 XML 语法将 JavaScript 表达式作为属性值时, this 对象可能出现指向错误的问题",
|
||||
"dialogs.build 方法 linkify 选项参数功能失效的问题",
|
||||
|
||||
@@ -18,19 +18,18 @@ import org.autojs.autojs.core.console.GlobalConsole
|
||||
import org.autojs.autojs.core.image.capture.ScreenCaptureRequester
|
||||
import org.autojs.autojs.core.looper.Loopers
|
||||
import org.autojs.autojs.core.pref.Pref
|
||||
import org.autojs.autojs.rhino.extension.ScriptableExtensions.defineProp
|
||||
import org.autojs.autojs.rhino.extension.ScriptableExtensions.prop
|
||||
import org.autojs.autojs.lang.ThreadCompat
|
||||
import org.autojs.autojs.pio.PFiles
|
||||
import org.autojs.autojs.pio.UncheckedIOException
|
||||
import org.autojs.autojs.rhino.AndroidClassLoader
|
||||
import org.autojs.autojs.rhino.ProxyObject
|
||||
import org.autojs.autojs.rhino.TopLevelScope
|
||||
import org.autojs.autojs.rhino.extension.ScriptableExtensions.defineProp
|
||||
import org.autojs.autojs.rhino.extension.ScriptableExtensions.prop
|
||||
import org.autojs.autojs.runtime.api.AbstractShell
|
||||
import org.autojs.autojs.runtime.api.AppUtils
|
||||
import org.autojs.autojs.runtime.api.ProcessShell
|
||||
import org.autojs.autojs.runtime.api.ScreenMetrics
|
||||
import org.autojs.autojs.runtime.api.ScriptToast
|
||||
import org.autojs.autojs.runtime.api.WrappedShizuku
|
||||
import org.autojs.autojs.runtime.api.augment.app.App
|
||||
import org.autojs.autojs.runtime.api.augment.autojs.Autojs
|
||||
@@ -183,7 +182,7 @@ class ScriptRuntime private constructor(builder: Builder) {
|
||||
private val mJob = SupervisorJob()
|
||||
val coroutineScope = CoroutineScope(Dispatchers.Default + mJob)
|
||||
val coroutineContext = coroutineScope.coroutineContext
|
||||
|
||||
|
||||
val ownerId = "runtime@${System.identityHashCode(this)}"
|
||||
|
||||
private var mUiHandlerAppContext: Context
|
||||
@@ -587,13 +586,13 @@ class ScriptRuntime private constructor(builder: Builder) {
|
||||
Log.d(TAG, "on exit")
|
||||
this.isExiting = true
|
||||
|
||||
ignoresException({
|
||||
ignoresException {
|
||||
if (console.configurator.isExitOnClose) {
|
||||
console.hideDelayed()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
ignoresException({ CoreWebSocket.onExit("Triggered by $TAG") })
|
||||
ignoresException { CoreWebSocket.onExit("Triggered by $TAG") }
|
||||
|
||||
// @Hint by 抠脚本人 (https://github.com/little-alei) on Jul 10, 2023.
|
||||
// ! 清空无障碍事件.
|
||||
@@ -604,35 +603,42 @@ class ScriptRuntime private constructor(builder: Builder) {
|
||||
// ! by the current script to avoid affecting other still-running scripts.
|
||||
// ! zh-CN: 只清理当前脚本注册的无障碍事件回调,避免影响其他仍在运行的脚本.
|
||||
// # ignoresException({ AccessibilityService.clearAccessibilityEventCallback() })
|
||||
ignoresException({ automator.removeAllEventsForThisRuntime() })
|
||||
ignoresException { automator.removeAllEventsForThisRuntime() }
|
||||
|
||||
ignoresException({ RootUtils.resetRuntimeOverriddenRootModeState() })
|
||||
ignoresException { RootUtils.resetRuntimeOverriddenRootModeState() }
|
||||
|
||||
/* 回收全部记录的 ImageWrapper 实例. */
|
||||
ignoresException({ CoreImageWrapper.recycleAll() })
|
||||
// Recycle all recorded ImageWrapper instances.
|
||||
// zh-CN: 回收全部记录的 ImageWrapper 实例.
|
||||
ignoresException { CoreImageWrapper.recycleAll() }
|
||||
|
||||
/* 清除 interrupt 状态. */
|
||||
ignoresException({ ThreadCompat.interrupted() })
|
||||
// Clear interrupt status.
|
||||
// zh-CN: 清除 interrupt 状态.
|
||||
ignoresException { ThreadCompat.interrupted() }
|
||||
|
||||
/* 浮动窗口需要第一时间关闭. */
|
||||
/* 以免出现恶意脚本全屏浮动窗口遮蔽屏幕并且在 exit 中写死循环的问题. */
|
||||
ignoresException({ floaty.closeAll() })
|
||||
// Floating windows need to be closed immediately.
|
||||
// To prevent malicious scripts from creating fullscreen floating windows
|
||||
// that obscure the screen and write infinite loops in exit.
|
||||
// zh-CN:
|
||||
// 浮动窗口需要第一时间关闭.
|
||||
// 以免出现恶意脚本全屏浮动窗口遮蔽屏幕并且在 exit 中写死循环的问题.
|
||||
ignoresException { floaty.closeAll() }
|
||||
|
||||
ignoresException({ events.emit("exit") }, "Exception on exit: %s")
|
||||
ignoresException({ ScriptToast.clear(this) }, 500)
|
||||
ignoresException("Exception on exit: %s") {
|
||||
events.emit("exit")
|
||||
}
|
||||
|
||||
ignoresException({ threads.shutDownAll() })
|
||||
ignoresException({ events.recycle() })
|
||||
ignoresException({ media.recycle() })
|
||||
ignoresException({ loopers.recycle() })
|
||||
ignoresException({ this.recycleShell() })
|
||||
ignoresException({ images.releaseScreenCapturer() })
|
||||
ignoresException({ images.stopScreenCapturerForegroundService() })
|
||||
ignoresException({ ocrMLKit.release() })
|
||||
ignoresException({ sensors.unregisterAll() })
|
||||
ignoresException({ timers.recycle() })
|
||||
ignoresException({ ui.recycle() })
|
||||
ignoresException({ closeableManager.recycleAll() })
|
||||
ignoresException { threads.shutDownAll() }
|
||||
ignoresException { events.recycle() }
|
||||
ignoresException { media.recycle() }
|
||||
ignoresException { loopers.recycle() }
|
||||
ignoresException { recycleShell() }
|
||||
ignoresException { images.releaseScreenCapturer() }
|
||||
ignoresException { images.stopScreenCapturerForegroundService() }
|
||||
ignoresException { ocrMLKit.release() }
|
||||
ignoresException { sensors.unregisterAll() }
|
||||
ignoresException { timers.recycle() }
|
||||
ignoresException { ui.recycle() }
|
||||
ignoresException { closeableManager.recycleAll() }
|
||||
}
|
||||
|
||||
fun setScreenMetrics(width: Int, height: Int) {
|
||||
@@ -709,11 +715,11 @@ class ScriptRuntime private constructor(builder: Builder) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun ignoresException(r: Runnable, @Suppress("SameParameterValue") delay: Int) {
|
||||
uiHandler.postDelayed(r, delay.toLong())
|
||||
private fun ignoresException(r: Runnable) {
|
||||
ignoresException(null, r)
|
||||
}
|
||||
|
||||
private fun ignoresException(r: Runnable, consoleMessage: String? = null) {
|
||||
private fun ignoresException(consoleMessage: String?, r: Runnable) {
|
||||
try {
|
||||
r.run()
|
||||
} catch (e: Throwable) {
|
||||
|
||||
@@ -1,40 +1,155 @@
|
||||
package org.autojs.autojs.runtime.api
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.widget.Toast
|
||||
import org.autojs.autojs.runtime.ScriptRuntime
|
||||
import java.lang.ref.WeakReference
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import java.util.ArrayDeque
|
||||
|
||||
/**
|
||||
* Toast global queue manager.
|
||||
* All scripts share a single global queue because only one toast can be shown at a time.
|
||||
*
|
||||
* zh-CN:
|
||||
*
|
||||
* Toast 全局队列管理器.
|
||||
* 所有脚本共享同一个全局队列, 因为同一时间通常只能显示一个 Toast.
|
||||
*
|
||||
* Created by SuperMonster003 on Aug 3, 2023.
|
||||
* Modified by SuperMonster003 as of Oct 24, 2023.
|
||||
* Transformed by SuperMonster003 on Oct 24, 2023.
|
||||
* Modified by JetBrains AI Assistant (GPT-5.2) as of Jan 30, 2026.
|
||||
* Modified by SuperMonster003 as of Jan 30, 2026.
|
||||
*/
|
||||
object ScriptToast {
|
||||
|
||||
@JvmField
|
||||
val pool = ConcurrentHashMap<Toast, WeakReference<ScriptRuntime>>()
|
||||
private const val MAX_GLOBAL_QUEUE_SIZE = 17
|
||||
|
||||
private val mainHandler = Handler(Looper.getMainLooper())
|
||||
private val queue = ArrayDeque<ToastTask>(MAX_GLOBAL_QUEUE_SIZE)
|
||||
|
||||
private var isShowing = false
|
||||
private var currentTask: ToastTask? = null
|
||||
private var currentToast: Toast? = null
|
||||
private var currentFinishRunnable: Runnable? = null
|
||||
|
||||
private data class ToastTask(
|
||||
val message: String,
|
||||
val duration: Int,
|
||||
val ownerId: String,
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
fun add(t: Toast, scriptRuntime: ScriptRuntime) {
|
||||
pool[t] = WeakReference(scriptRuntime)
|
||||
fun enqueueToast(context: Context, scriptRuntime: ScriptRuntime, message: String, isLong: Boolean = false) {
|
||||
val duration = if (isLong) Toast.LENGTH_LONG else Toast.LENGTH_SHORT
|
||||
val ownerId = scriptRuntime.ownerId
|
||||
|
||||
// Must be called on the main thread.
|
||||
// zh-CN: 必须在主线程调用.
|
||||
if (Looper.myLooper() != Looper.getMainLooper()) {
|
||||
mainHandler.post { enqueueToast(context, scriptRuntime, message, isLong) }
|
||||
return
|
||||
}
|
||||
|
||||
if (queue.size >= MAX_GLOBAL_QUEUE_SIZE) {
|
||||
// Discard newest task when the queue is full.
|
||||
// zh-CN: 当队列已满时丢弃最新任务.
|
||||
return
|
||||
}
|
||||
|
||||
queue.addLast(ToastTask(message, duration, ownerId))
|
||||
|
||||
tryShowNextLocked(context.applicationContext)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun dismissAll(scriptRuntime: ScriptRuntime) {
|
||||
pool.entries.forEach { entry ->
|
||||
if (entry.value.get() == scriptRuntime) {
|
||||
pool.remove(entry.key)
|
||||
entry.key.cancel()
|
||||
val ownerId = scriptRuntime.ownerId
|
||||
mainHandler.post {
|
||||
queue.removeAll { it.ownerId == ownerId }
|
||||
|
||||
if (currentTask?.ownerId == ownerId) {
|
||||
currentFinishRunnable?.let { mainHandler.removeCallbacks(it) }
|
||||
currentFinishRunnable = null
|
||||
|
||||
currentToast?.cancel()
|
||||
currentToast = null
|
||||
currentTask = null
|
||||
isShowing = false
|
||||
|
||||
tryShowNextLocked(scriptRuntime.uiHandler.applicationContext)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun clear(scriptRuntime: ScriptRuntime) {
|
||||
pool.entries
|
||||
.filter { it.value.get() == scriptRuntime }
|
||||
.forEach { pool.remove(it.key) }
|
||||
val ownerId = scriptRuntime.ownerId
|
||||
mainHandler.post {
|
||||
queue.removeAll { it.ownerId == ownerId }
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun destroy() {
|
||||
mainHandler.post {
|
||||
queue.clear()
|
||||
|
||||
currentFinishRunnable?.let { mainHandler.removeCallbacks(it) }
|
||||
currentFinishRunnable = null
|
||||
|
||||
currentToast?.cancel()
|
||||
currentToast = null
|
||||
currentTask = null
|
||||
isShowing = false
|
||||
}
|
||||
}
|
||||
|
||||
private fun tryShowNextLocked(appCtx: Context) {
|
||||
if (isShowing) return
|
||||
|
||||
val task = queue.removeFirstOrNull() ?: return
|
||||
|
||||
isShowing = true
|
||||
currentTask = task
|
||||
|
||||
val toast = Toast.makeText(appCtx, task.message, task.duration)
|
||||
currentToast = toast
|
||||
|
||||
val finish = Runnable {
|
||||
currentFinishRunnable = null
|
||||
currentToast = null
|
||||
currentTask = null
|
||||
isShowing = false
|
||||
tryShowNextLocked(appCtx)
|
||||
}
|
||||
currentFinishRunnable = finish
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
toast.addCallback(object : Toast.Callback() {
|
||||
override fun onToastHidden() {
|
||||
super.onToastHidden()
|
||||
finish.run()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
val delay = if (task.duration == Toast.LENGTH_LONG) 3_500L else 2_000L
|
||||
mainHandler.postDelayed(finish, delay)
|
||||
}
|
||||
|
||||
toast.show()
|
||||
}
|
||||
|
||||
private fun <E> ArrayDeque<E>.removeFirstOrNull(): E? =
|
||||
if (isEmpty()) null else removeFirst()
|
||||
|
||||
private inline fun <E> ArrayDeque<E>.removeAll(predicate: (E) -> Boolean) {
|
||||
if (isEmpty()) return
|
||||
val it = iterator()
|
||||
while (it.hasNext()) {
|
||||
if (predicate(it.next())) it.remove()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package org.autojs.autojs.runtime.api.augment.toast
|
||||
|
||||
import org.autojs.autojs.AutoJs
|
||||
import org.autojs.autojs.annotation.RhinoFunctionBody
|
||||
import org.autojs.autojs.annotation.RhinoRuntimeFunctionInterface
|
||||
import org.autojs.autojs.rhino.ArgumentGuards
|
||||
import org.autojs.autojs.runtime.ScriptRuntime
|
||||
import org.autojs.autojs.runtime.api.ScriptToast
|
||||
import org.autojs.autojs.runtime.api.augment.Augmentable
|
||||
import org.autojs.autojs.runtime.api.augment.Invokable
|
||||
import org.autojs.autojs.util.RhinoUtils.undefined
|
||||
import org.autojs.autojs.runtime.exception.WrappedIllegalArgumentException
|
||||
import org.autojs.autojs.util.RhinoUtils.UNDEFINED
|
||||
import org.mozilla.javascript.Undefined
|
||||
|
||||
class Toast(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime), Invokable {
|
||||
@@ -35,26 +35,22 @@ class Toast(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntim
|
||||
@JvmStatic
|
||||
@RhinoRuntimeFunctionInterface
|
||||
fun call(scriptRuntime: ScriptRuntime, args: Array<out Any?>): Undefined = ensureArgumentsLengthInRange(args, 0..3) {
|
||||
undefined {
|
||||
when (it.size) {
|
||||
0 -> ToastParser("").show(scriptRuntime)
|
||||
1 -> ToastParser(args[0]).show(scriptRuntime)
|
||||
2 -> ToastParser(args[0], args[1]).show(scriptRuntime)
|
||||
3 -> ToastParser(args[0], args[1], args[2]).show(scriptRuntime)
|
||||
}
|
||||
val toastParser = when (it.size) {
|
||||
0 -> ToastParser(globalContext, "")
|
||||
1 -> ToastParser(globalContext, args[0])
|
||||
2 -> ToastParser(globalContext, args[0], args[1])
|
||||
3 -> ToastParser(globalContext, args[0], args[1], args[2])
|
||||
else -> throw WrappedIllegalArgumentException("Invalid arguments length ${args.size} for global.toast")
|
||||
}
|
||||
toastParser.show(scriptRuntime)
|
||||
return@ensureArgumentsLengthInRange UNDEFINED
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@RhinoRuntimeFunctionInterface
|
||||
fun dismissAll(scriptRuntime: ScriptRuntime, args: Array<out Any?>): Undefined = ensureArgumentsIsEmpty(args) {
|
||||
dismissAllRhino(scriptRuntime)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@RhinoFunctionBody
|
||||
fun dismissAllRhino(scriptRuntime: ScriptRuntime) = undefined {
|
||||
AutoJs.instance.uiHandler.dismissAllToasts(scriptRuntime)
|
||||
ScriptToast.dismissAll(scriptRuntime)
|
||||
return@ensureArgumentsIsEmpty UNDEFINED
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
package org.autojs.autojs.runtime.api.augment.toast
|
||||
|
||||
import org.autojs.autojs.AutoJs
|
||||
import org.autojs.autojs.rhino.extension.AnyExtensions.jsBrief
|
||||
import org.autojs.autojs.runtime.ScriptRuntime
|
||||
import org.autojs.autojs.util.RhinoUtils.coerceString
|
||||
import org.mozilla.javascript.Context
|
||||
import org.autojs.autojs.runtime.api.ScriptToast
|
||||
import org.mozilla.javascript.Scriptable.NOT_FOUND
|
||||
import org.mozilla.javascript.Undefined
|
||||
import android.content.Context as AndroidContext
|
||||
import org.mozilla.javascript.Context as RhinoContext
|
||||
|
||||
class ToastParser(private val msg: Any?, long: Any? = null, forcible: Any? = null) {
|
||||
/**
|
||||
* Created by SuperMonster003 on Dec 2, 2024.
|
||||
* Modified by SuperMonster003 as of Jan 30, 2026.
|
||||
*/
|
||||
class ToastParser(private val context: AndroidContext, private val msg: Any?, isLong: Any? = null, isForcible: Any? = null) {
|
||||
|
||||
private val badge = object {
|
||||
val long = Regex("^l(ong)?$", RegexOption.IGNORE_CASE)
|
||||
@@ -20,42 +24,42 @@ class ToastParser(private val msg: Any?, long: Any? = null, forcible: Any? = nul
|
||||
var isForcible = false
|
||||
|
||||
init {
|
||||
parseIsLong(long)
|
||||
parseIsForcible(forcible)
|
||||
parseIsLong(isLong)
|
||||
parseIsForcible(isForcible)
|
||||
}
|
||||
|
||||
fun show(scriptRuntime: ScriptRuntime) {
|
||||
if (isForcible) Toast.dismissAllRhino(scriptRuntime)
|
||||
if (this@ToastParser.isForcible) ScriptToast.dismissAll(scriptRuntime)
|
||||
val niceMsg = when {
|
||||
Undefined.isUndefined(msg) || msg == NOT_FOUND -> "undefined"
|
||||
msg == null -> "null"
|
||||
else -> Context.toString(msg)
|
||||
else -> RhinoContext.toString(msg)
|
||||
}
|
||||
AutoJs.instance.uiHandler.toast(scriptRuntime, niceMsg, isLong)
|
||||
ScriptToast.enqueueToast(context, scriptRuntime, niceMsg, this@ToastParser.isLong)
|
||||
}
|
||||
|
||||
private fun parseIsLong(o: Any?) = when (o) {
|
||||
is Boolean -> o
|
||||
is Number -> Context.toBoolean(o)
|
||||
is Number -> RhinoContext.toBoolean(o)
|
||||
is String -> when {
|
||||
badge.long.matches(o) -> true
|
||||
badge.short.matches(o) -> false
|
||||
badge.forcible.matches(o) -> isLong.also { this.isForcible = true }
|
||||
badge.forcible.matches(o) -> this@ToastParser.isLong.also { this.isForcible = true }
|
||||
else -> throw IllegalArgumentException("Argument \"isLong\" ${o.jsBrief()} for Toast.Parser is invalid")
|
||||
}
|
||||
else -> isLong
|
||||
}.also { isLong = it }
|
||||
else -> this@ToastParser.isLong
|
||||
}.also { this@ToastParser.isLong = it }
|
||||
|
||||
private fun parseIsForcible(o: Any?) = when (o) {
|
||||
is Boolean -> o
|
||||
is Number -> Context.toBoolean(o)
|
||||
is Number -> RhinoContext.toBoolean(o)
|
||||
is String -> when {
|
||||
badge.forcible.matches(o) -> true
|
||||
badge.long.matches(o) -> isForcible.also { this.isLong = true }
|
||||
badge.short.matches(o) -> isForcible.also { this.isLong = false }
|
||||
badge.long.matches(o) -> this@ToastParser.isForcible.also { this.isLong = true }
|
||||
badge.short.matches(o) -> this@ToastParser.isForcible.also { this.isLong = false }
|
||||
else -> throw IllegalArgumentException("Argument \"isForcible\" ${o.jsBrief()} for Toast.Parser is invalid")
|
||||
}
|
||||
else -> isForcible
|
||||
}.also { isForcible = it }
|
||||
else -> this@ToastParser.isForcible
|
||||
}.also { this@ToastParser.isForcible = it }
|
||||
|
||||
}
|
||||
@@ -3,33 +3,10 @@ package org.autojs.autojs.tool
|
||||
import android.content.Context
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.widget.Toast
|
||||
import android.widget.Toast.LENGTH_LONG
|
||||
import android.widget.Toast.LENGTH_SHORT
|
||||
import org.autojs.autojs.AutoJs
|
||||
import org.autojs.autojs.runtime.ScriptRuntime
|
||||
import org.autojs.autojs.runtime.api.ScriptToast
|
||||
import org.autojs.autojs.util.RhinoUtils.isMainThread
|
||||
|
||||
/**
|
||||
* Created by Stardust on May 2, 2017.
|
||||
* Transformed by SuperMonster003 on Oct 25, 2023.
|
||||
* Modified by SuperMonster003 as of Jan 30, 2026.
|
||||
*/
|
||||
class UiHandler(val applicationContext: Context) : Handler(Looper.getMainLooper()) {
|
||||
|
||||
fun toast(scriptRuntime: ScriptRuntime, message: String, isLong: Boolean = false) {
|
||||
val showRunnable = Runnable {
|
||||
val toastLength = if (isLong) LENGTH_LONG else LENGTH_SHORT
|
||||
Toast.makeText(AutoJs.instance.application, message, toastLength)
|
||||
.also { ScriptToast.add(it, scriptRuntime) }
|
||||
.show()
|
||||
}
|
||||
when {
|
||||
isMainThread() -> showRunnable.run()
|
||||
else -> this@UiHandler.post(showRunnable)
|
||||
}
|
||||
}
|
||||
|
||||
fun dismissAllToasts(scriptRuntime: ScriptRuntime) = ScriptToast.dismissAll(scriptRuntime)
|
||||
|
||||
}
|
||||
class UiHandler(val applicationContext: Context) : Handler(Looper.getMainLooper())
|
||||
|
||||
@@ -6,8 +6,6 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.view.Gravity
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
@@ -347,12 +345,9 @@ class MainActivity : BaseActivity(), DelegateHost, HostActivity {
|
||||
}
|
||||
|
||||
private fun setUpStatusBarIconLight() {
|
||||
Handler(Looper.getMainLooper()).post {
|
||||
if (sIsActionBarDrawerOpened) {
|
||||
setUpStatusBarIconLightByNightMode()
|
||||
} else {
|
||||
setUpStatusBarIconLightByThemeColor()
|
||||
}
|
||||
when (sIsActionBarDrawerOpened) {
|
||||
true -> setUpStatusBarIconLightByNightMode()
|
||||
else -> setUpStatusBarIconLightByThemeColor()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#Wed Jan 28 21:05:38 CST 2026
|
||||
BUILD_TIME=1769605538543
|
||||
#Fri Jan 30 20:56:33 CST 2026
|
||||
BUILD_TIME=1769777793096
|
||||
COMPILE_SDK_VERSION=36
|
||||
IMAGE_QUANT_CMAKE_VERSION=3.22.1
|
||||
IMAGE_QUANT_NDK_VERSION=26.1.10909125
|
||||
@@ -27,6 +27,6 @@ RAPID_OCR_OPENCV_MOBILE_LABEL_VERSION=13
|
||||
RAPID_OCR_OPENCV_MOBILE_VERSION=4.5.3
|
||||
TARGET_SDK_VERSION=36
|
||||
TARGET_SDK_VERSION_INRT=29
|
||||
VERSION_BUILD=3666
|
||||
VERSION_BUILD=3673
|
||||
VERSION_NAME=6.7.0 Alpha18
|
||||
VSCODE_EXT_REQUIRED_VERSION=1.0.13
|
||||
|
||||
Reference in New Issue
Block a user