6.7.0 - Alpha13 - 选择器支持正则表达式标志 (i, m, s, u); 等价系列及包含系列选择器支持正则表达式参数

This commit is contained in:
SuperMonster003
2025-12-27 22:12:15 +08:00
parent 79787b6b53
commit ebf4489655
29 changed files with 422 additions and 213 deletions

View File

@@ -23,6 +23,8 @@
"UiObject#isShifted 方法, 用于检测控件位置变化",
"crash 全局方法, 用于测试崩溃报告页面",
"structuredClone 全局方法, 用于深拷贝 JavaScript 对象 (参阅 [MDN](https://developer.mozilla.org/zh-CN/docs/Web/API/Window/structuredClone))",
"等价系列选择器 (UiSelector#id/text/...) 及包含系列选择器 (UiSelector#xxxContains) 支持正则表达式参数",
"选择器的正则表达式参数支持使用标志 (i, m, s, u)",
"设置页面增加 \"Java 原始类型包装\" 设置选项 _[`issue #435`](http://issues.autojs6.com/435)_",
"设置页面增加 \"定时任务调度引擎\" 设置选项, 支持 AlarmManager/WorkManager/JobScheduler _[`issue #457`](http://issues.autojs6.com/457)_ _[`issue #388`](http://issues.autojs6.com/388)_ _[`issue #163`](http://issues.autojs6.com/163)_ _[`issue #53`](http://issues.autojs6.com/53)_ _[`issue #21`](http://issues.autojs6.com/21)_",
"设置页面增加 \"应用启动器图标\" 设置选项, 支持自适应图标/透明背景图标 _[`issue #405`](http://issues.autojs6.com/405)_",

View File

@@ -48,7 +48,6 @@ import org.autojs.autojs.runtime.exception.ScriptInterruptedException
import org.autojs.autojs.util.App
import org.autojs.autojs.util.RhinoUtils
import org.autojs.autojs.util.RhinoUtils.isMainThread
import org.autojs.autojs.util.StringUtils.convertRegex
import org.autojs.autojs.util.StringUtils.str
import org.autojs.autojs6.R
import org.mozilla.javascript.BaseFunction
@@ -83,7 +82,10 @@ open class UiSelector : UiObjectActions, StringReadable {
}
@ScriptInterface
fun id(str: String) = also { addFilter(IdFilter.equals(str)) }
fun id(s: String) = also { addFilter(IdFilter.equals(s)) }
@ScriptInterface
fun id(regex: NativeRegExp) = also { addFilter(IdFilter.equals(regex)) }
@ScriptInterface
fun idStartsWith(prefix: String) = also { addFilter(IdFilter.startsWith(prefix)) }
@@ -92,28 +94,34 @@ open class UiSelector : UiObjectActions, StringReadable {
fun idEndsWith(suffix: String) = also { addFilter(IdFilter.endsWith(suffix)) }
@ScriptInterface
fun idContains(str: String) = also { addFilter(IdFilter.contains(str)) }
fun idContains(s: String) = also { addFilter(IdFilter.contains(s)) }
@ScriptInterface
@Deprecated("Deprecated in Java", ReplaceWith("idMatch(regex)"))
fun idMatches(regex: String) = also { addFilter(IdFilter.matches(convertRegex(regex))) }
fun idContains(regex: NativeRegExp) = also { addFilter(IdFilter.contains(regex)) }
@ScriptInterface
@Deprecated("Deprecated in Java", ReplaceWith("idMatch(s)"))
fun idMatches(s: String) = also { addFilter(IdFilter.matches(s)) }
@ScriptInterface
@Suppress("DEPRECATION")
@Deprecated("Deprecated in Java", ReplaceWith("idMatch(regex)"))
fun idMatches(regex: NativeRegExp) = idMatches(regex.toString())
fun idMatches(regex: NativeRegExp) = also { addFilter(IdFilter.matches(regex)) }
@ScriptInterface
fun idMatch(regex: String) = also { addFilter(IdFilter.match(regex)) }
fun idMatch(s: String) = also { addFilter(IdFilter.match(s)) }
@ScriptInterface
fun idMatch(regex: NativeRegExp) = idMatch(convertRegex(regex.toString()))
fun idMatch(regex: NativeRegExp) = also { addFilter(IdFilter.match(regex)) }
@ScriptInterface
fun idHex(str: String) = also { addFilter(IdHexFilter.equals(str)) }
@ScriptInterface
fun text(str: String) = also { addFilter(TextFilter.equals(str)) }
fun text(s: String) = also { addFilter(TextFilter.equals(s)) }
@ScriptInterface
fun text(regex: NativeRegExp) = also { addFilter(TextFilter.equals(regex)) }
@ScriptInterface
fun textStartsWith(prefix: String) = also { addFilter(TextFilter.startsWith(prefix)) }
@@ -122,25 +130,31 @@ open class UiSelector : UiObjectActions, StringReadable {
fun textEndsWith(suffix: String) = also { addFilter(TextFilter.endsWith(suffix)) }
@ScriptInterface
fun textContains(str: String) = also { addFilter(TextFilter.contains(str)) }
fun textContains(s: String) = also { addFilter(TextFilter.contains(s)) }
@ScriptInterface
@Deprecated("Deprecated in Java", ReplaceWith("textMatch(regex)"))
fun textMatches(regex: String) = also { addFilter(TextFilter.matches(convertRegex(regex))) }
fun textContains(regex: NativeRegExp) = also { addFilter(TextFilter.contains(regex)) }
@ScriptInterface
@Deprecated("Deprecated in Java", ReplaceWith("textMatch(s)"))
fun textMatches(s: String) = also { addFilter(TextFilter.matches(s)) }
@ScriptInterface
@Suppress("DEPRECATION")
@Deprecated("Deprecated in Java", ReplaceWith("textMatch(regex)"))
fun textMatches(regex: NativeRegExp) = textMatches(regex.toString())
fun textMatches(regex: NativeRegExp) = also { addFilter(TextFilter.matches(regex)) }
@ScriptInterface
fun textMatch(regex: String) = also { addFilter(TextFilter.match(regex)) }
fun textMatch(s: String) = also { addFilter(TextFilter.match(s)) }
@ScriptInterface
fun textMatch(regex: NativeRegExp) = textMatch(convertRegex(regex.toString()))
fun textMatch(regex: NativeRegExp) = also { addFilter(TextFilter.match(regex)) }
@ScriptInterface
fun desc(str: String) = also { addFilter(DescFilter.equals(str)) }
fun desc(s: String) = also { addFilter(DescFilter.equals(s)) }
@ScriptInterface
fun desc(regex: NativeRegExp) = also { addFilter(DescFilter.equals(regex)) }
@ScriptInterface
fun descStartsWith(prefix: String) = also { addFilter(DescFilter.startsWith(prefix)) }
@@ -149,25 +163,31 @@ open class UiSelector : UiObjectActions, StringReadable {
fun descEndsWith(suffix: String) = also { addFilter(DescFilter.endsWith(suffix)) }
@ScriptInterface
fun descContains(str: String) = also { addFilter(DescFilter.contains(str)) }
fun descContains(s: String) = also { addFilter(DescFilter.contains(s)) }
@ScriptInterface
fun descContains(regex: NativeRegExp) = also { addFilter(DescFilter.contains(regex)) }
@ScriptInterface
@Deprecated("Deprecated in Java", ReplaceWith("descMatch(regex)"))
fun descMatches(regex: String) = also { addFilter(DescFilter.matches(convertRegex(regex))) }
@Deprecated("Deprecated in Java", ReplaceWith("descMatch(s)"))
fun descMatches(s: String) = also { addFilter(DescFilter.matches(s)) }
@ScriptInterface
@Suppress("DEPRECATION")
@Deprecated("Deprecated in Java", ReplaceWith("descMatch(regex)"))
fun descMatches(regex: NativeRegExp) = descMatches(regex.toString())
fun descMatches(regex: NativeRegExp) = also { addFilter(DescFilter.matches(regex)) }
@ScriptInterface
fun descMatch(regex: String) = also { addFilter(DescFilter.match(regex)) }
fun descMatch(s: String) = also { addFilter(DescFilter.match(s)) }
@ScriptInterface
fun descMatch(regex: NativeRegExp) = descMatch(convertRegex(regex.toString()))
fun descMatch(regex: NativeRegExp) = also { addFilter(DescFilter.match(regex)) }
@ScriptInterface
fun content(str: String) = also { addFilter(ContentFilter.equals(str)) }
fun content(s: String) = also { addFilter(ContentFilter.equals(s)) }
@ScriptInterface
fun content(regex: NativeRegExp) = also { addFilter(ContentFilter.equals(regex)) }
@ScriptInterface
fun contentStartsWith(prefix: String) = also { addFilter(ContentFilter.startsWith(prefix)) }
@@ -176,25 +196,31 @@ open class UiSelector : UiObjectActions, StringReadable {
fun contentEndsWith(suffix: String) = also { addFilter(ContentFilter.endsWith(suffix)) }
@ScriptInterface
fun contentContains(str: String) = also { addFilter(ContentFilter.contains(str)) }
fun contentContains(s: String) = also { addFilter(ContentFilter.contains(s)) }
@ScriptInterface
fun contentContains(regex: NativeRegExp) = also { addFilter(ContentFilter.contains(regex)) }
@ScriptInterface
@Deprecated("Deprecated in Java", ReplaceWith("contentMatch(regex)"))
fun contentMatches(regex: String) = also { addFilter(ContentFilter.matches(convertRegex(regex))) }
@Deprecated("Deprecated in Java", ReplaceWith("contentMatch(s)"))
fun contentMatches(s: String) = also { addFilter(ContentFilter.matches(s)) }
@ScriptInterface
@Suppress("DEPRECATION")
@Deprecated("Deprecated in Java", ReplaceWith("contentMatch(regex)"))
fun contentMatches(regex: NativeRegExp) = contentMatches(regex.toString())
fun contentMatches(regex: NativeRegExp) = also { addFilter(ContentFilter.matches(regex)) }
@ScriptInterface
fun contentMatch(regex: String) = also { addFilter(ContentFilter.match(regex)) }
fun contentMatch(s: String) = also { addFilter(ContentFilter.match(s)) }
@ScriptInterface
fun contentMatch(regex: NativeRegExp) = contentMatch(convertRegex(regex.toString()))
fun contentMatch(regex: NativeRegExp) = also { addFilter(ContentFilter.match(regex)) }
@ScriptInterface
fun className(str: String) = also { addFilter(ClassNameFilter.equals(str)) }
fun className(s: String) = also { addFilter(ClassNameFilter.equals(s)) }
@ScriptInterface
fun className(regex: NativeRegExp) = also { addFilter(ClassNameFilter.equals(regex)) }
@ScriptInterface
fun classNameStartsWith(prefix: String) = also { addFilter(ClassNameFilter.startsWith(prefix)) }
@@ -203,25 +229,31 @@ open class UiSelector : UiObjectActions, StringReadable {
fun classNameEndsWith(suffix: String) = also { addFilter(ClassNameFilter.endsWith(suffix)) }
@ScriptInterface
fun classNameContains(str: String) = also { addFilter(ClassNameFilter.contains(str)) }
fun classNameContains(s: String) = also { addFilter(ClassNameFilter.contains(s)) }
@ScriptInterface
@Deprecated("Deprecated in Java", ReplaceWith("classNameMatch(regex)"))
fun classNameMatches(regex: String) = also { addFilter(ClassNameFilter.matches(convertRegex(regex))) }
fun classNameContains(regex: NativeRegExp) = also { addFilter(ClassNameFilter.contains(regex)) }
@ScriptInterface
@Deprecated("Deprecated in Java", ReplaceWith("classNameMatch(s)"))
fun classNameMatches(s: String) = also { addFilter(ClassNameFilter.matches(s)) }
@ScriptInterface
@Suppress("DEPRECATION")
@Deprecated("Deprecated in Java", ReplaceWith("classNameMatch(regex)"))
fun classNameMatches(regex: NativeRegExp) = classNameMatches(regex.toString())
fun classNameMatches(regex: NativeRegExp) = also { addFilter(ClassNameFilter.matches(regex)) }
@ScriptInterface
fun classNameMatch(regex: String) = also { addFilter(ClassNameFilter.match(regex)) }
fun classNameMatch(s: String) = also { addFilter(ClassNameFilter.match(s)) }
@ScriptInterface
fun classNameMatch(regex: NativeRegExp) = classNameMatch(convertRegex(regex.toString()))
fun classNameMatch(regex: NativeRegExp) = also { addFilter(ClassNameFilter.match(regex)) }
@ScriptInterface
fun packageName(str: String) = also { addFilter(PackageNameFilter.equals(str)) }
fun packageName(s: String) = also { addFilter(PackageNameFilter.equals(s)) }
@ScriptInterface
fun packageName(regex: NativeRegExp) = also { addFilter(PackageNameFilter.equals(regex)) }
@ScriptInterface
fun packageName(app: App) = also { addFilter(PackageNameFilter.equals(app.packageName)) }
@@ -233,22 +265,25 @@ open class UiSelector : UiObjectActions, StringReadable {
fun packageNameEndsWith(suffix: String) = also { addFilter(PackageNameFilter.endsWith(suffix)) }
@ScriptInterface
fun packageNameContains(str: String) = also { addFilter(PackageNameFilter.contains(str)) }
fun packageNameContains(s: String) = also { addFilter(PackageNameFilter.contains(s)) }
@ScriptInterface
fun packageNameContains(regex: NativeRegExp) = also { addFilter(PackageNameFilter.contains(regex)) }
@ScriptInterface
@Deprecated("Deprecated in Java", ReplaceWith("packageNameMatch(regex)"))
fun packageNameMatches(regex: String) = also { addFilter(PackageNameFilter.matches(convertRegex(regex))) }
@Deprecated("Deprecated in Java", ReplaceWith("packageNameMatch(s)"))
fun packageNameMatches(s: String) = also { addFilter(PackageNameFilter.matches(s)) }
@ScriptInterface
@Suppress("DEPRECATION")
@Deprecated("Deprecated in Java", ReplaceWith("packageNameMatch(regex)"))
fun packageNameMatches(regex: NativeRegExp) = packageNameMatches(regex.toString())
fun packageNameMatches(regex: NativeRegExp) = also { addFilter(PackageNameFilter.matches(regex)) }
@ScriptInterface
fun packageNameMatch(regex: String) = also { addFilter(PackageNameFilter.match(regex)) }
fun packageNameMatch(s: String) = also { addFilter(PackageNameFilter.match(s)) }
@ScriptInterface
fun packageNameMatch(regex: NativeRegExp) = packageNameMatch(convertRegex(regex.toString()))
fun packageNameMatch(regex: NativeRegExp) = also { addFilter(PackageNameFilter.match(regex)) }
@ScriptInterface
fun currentApp(app: App) = also { addFilter(AppFilter(app)) }
@@ -1019,7 +1054,7 @@ open class UiSelector : UiObjectActions, StringReadable {
.invoke(tmp)
is String -> tmp::class.java
.getMethod(key, cString)
.invoke(tmp, value.toString())
.invoke(tmp, value)
is NativeRegExp -> tmp::class.java
.getMethod(key, cNativeRegExp)
.invoke(tmp, value)

View File

@@ -1,10 +1,11 @@
package org.autojs.autojs.core.automator.filter
import org.autojs.autojs.core.automator.UiObject
import org.mozilla.javascript.regexp.NativeRegExp
/**
* Created by Stardust on Mar 9, 2017.
* Modified by SuperMonster003 as of Nov 19, 2022.
* Modified by SuperMonster003 as of Dec 27, 2025.
*/
object ClassNameFilter {
@@ -59,7 +60,11 @@ object ClassNameFilter {
else -> extendedClassNameMap[text] ?: "android.widget.$text"
}.let { StringEqualsFilter(it, CLASS_NAME_GETTER) }
fun contains(str: String) = StringContainsFilter(str, CLASS_NAME_GETTER)
@Suppress("CovariantEquals")
fun equals(regex: NativeRegExp) = StringEqualsFilter(regex, CLASS_NAME_GETTER)
fun contains(s: String) = StringContainsFilter(s, CLASS_NAME_GETTER)
fun contains(regex: NativeRegExp) = StringContainsFilter(regex, CLASS_NAME_GETTER)
fun startsWith(prefix: String) = when (prefix.contains(".")) {
true -> prefix
@@ -68,8 +73,10 @@ object ClassNameFilter {
fun endsWith(suffix: String) = StringEndsWithFilter(suffix, CLASS_NAME_GETTER)
fun matches(regex: String) = StringMatchesFilter(regex, CLASS_NAME_GETTER)
fun matches(s: String) = StringMatchesFilter(s, CLASS_NAME_GETTER)
fun matches(regex: NativeRegExp) = StringMatchesFilter(regex, CLASS_NAME_GETTER)
fun match(regex: String) = StringMatchFilter(regex, CLASS_NAME_GETTER)
fun match(s: String) = StringMatchFilter(s, CLASS_NAME_GETTER)
fun match(regex: NativeRegExp) = StringMatchFilter(regex, CLASS_NAME_GETTER)
}

View File

@@ -1,9 +1,11 @@
package org.autojs.autojs.core.automator.filter
import org.autojs.autojs.core.automator.UiObject
import org.mozilla.javascript.regexp.NativeRegExp
/**
* Created by SuperMonster003 on Jun 10, 2022.
* Modified by SuperMonster003 as of Dec 27, 2025.
*/
object ContentFilter {
@@ -15,16 +17,23 @@ object ContentFilter {
}
fun equals(text: String) = StringListEqualsFilter(text, CONTENT_GETTER)
@Suppress("CovariantEquals")
fun equals(s: String) = StringListEqualsFilter(s, CONTENT_GETTER)
fun contains(str: String) = StringListContainsFilter(str, CONTENT_GETTER)
@Suppress("CovariantEquals")
fun equals(regex: NativeRegExp) = StringListEqualsFilter(regex, CONTENT_GETTER)
fun contains(s: String) = StringListContainsFilter(s, CONTENT_GETTER)
fun contains(regex: NativeRegExp) = StringListContainsFilter(regex, CONTENT_GETTER)
fun startsWith(prefix: String) = StringListStartsWithFilter(prefix, CONTENT_GETTER)
fun endsWith(suffix: String) = StringListEndsWithFilter(suffix, CONTENT_GETTER)
fun matches(regex: String) = StringListMatchesFilter(regex, CONTENT_GETTER)
fun matches(s: String) = StringListMatchesFilter(s, CONTENT_GETTER)
fun matches(regex: NativeRegExp) = StringListMatchesFilter(regex, CONTENT_GETTER)
fun match(regex: String) = StringListMatchFilter(regex, CONTENT_GETTER)
fun match(s: String) = StringListMatchFilter(s, CONTENT_GETTER)
fun match(regex: NativeRegExp) = StringListMatchFilter(regex, CONTENT_GETTER)
}

View File

@@ -1,10 +1,11 @@
package org.autojs.autojs.core.automator.filter
import org.autojs.autojs.core.automator.UiObject
import org.mozilla.javascript.regexp.NativeRegExp
/**
* Created by Stardust on Mar 9, 2017.
* Modified by SuperMonster003 as of Nov 19, 2022.
* Modified by SuperMonster003 as of Dec 27, 2025.
*/
object DescFilter {
@@ -16,16 +17,23 @@ object DescFilter {
}
fun equals(text: String) = StringEqualsFilter(text, DESC_GETTER)
@Suppress("CovariantEquals")
fun equals(s: String) = StringEqualsFilter(s, DESC_GETTER)
fun contains(str: String) = StringContainsFilter(str, DESC_GETTER)
@Suppress("CovariantEquals")
fun equals(regex: NativeRegExp) = StringEqualsFilter(regex, DESC_GETTER)
fun contains(s: String) = StringContainsFilter(s, DESC_GETTER)
fun contains(regex: NativeRegExp) = StringContainsFilter(regex, DESC_GETTER)
fun startsWith(prefix: String) = StringStartsWithFilter(prefix, DESC_GETTER)
fun endsWith(suffix: String) = StringEndsWithFilter(suffix, DESC_GETTER)
fun matches(regex: String) = StringMatchesFilter(regex, DESC_GETTER)
fun matches(s: String) = StringMatchesFilter(s, DESC_GETTER)
fun matches(regex: NativeRegExp) = StringMatchesFilter(regex, DESC_GETTER)
fun match(regex: String) = StringMatchFilter(regex, DESC_GETTER)
fun match(s: String) = StringMatchFilter(s, DESC_GETTER)
fun match(regex: NativeRegExp) = StringMatchFilter(regex, DESC_GETTER)
}

View File

@@ -2,10 +2,11 @@ package org.autojs.autojs.core.automator.filter
import org.autojs.autojs.core.accessibility.UiSelector.Companion.ID_IDENTIFIER
import org.autojs.autojs.core.automator.UiObject
import org.mozilla.javascript.regexp.NativeRegExp
/**
* Created by Stardust on Mar 9, 2017.
* Modified by SuperMonster003 as of Nov 19, 2022.
* Modified by SuperMonster003 as of Dec 27, 2025.
*/
object IdFilter {
@@ -18,17 +19,27 @@ object IdFilter {
}
@Suppress("CovariantEquals")
fun equals(str: String) = when (str.contains(ID_IDENTIFIER)) {
true -> StringEqualsFilter(str, ID_GETTER)
fun equals(s: String) = when (s.contains(ID_IDENTIFIER)) {
true -> StringEqualsFilter(s, ID_GETTER)
else -> object : Filter {
override fun filter(node: UiObject) = node.id()?.let { id ->
when (id.contains(ID_IDENTIFIER)) {
true -> id.split(ID_IDENTIFIER).last() == str
else -> id == str
true -> id.split(ID_IDENTIFIER).last() == s
else -> id == s
}
} ?: false
override fun toString() = "id(\"$str\")"
override fun toString() = "${ID_GETTER}(\"$s\")"
}
}
@Suppress("CovariantEquals")
fun equals(regex: NativeRegExp): Filter {
return object : StringMatchesFilter(regex, ID_GETTER) {
override fun toString(): String {
val literal = JsRegexUtils.formatAsJsRegexLiteral(regex.toString())
return "${ID_GETTER}($literal)"
}
}
}
@@ -42,16 +53,19 @@ object IdFilter {
}
} ?: false
override fun toString() = "idStartsWith(\"$prefix\")"
override fun toString() = "${ID_GETTER}StartsWith(\"$prefix\")"
}
}
fun endsWith(suffix: String) = StringEndsWithFilter(suffix, ID_GETTER)
fun contains(contains: String) = StringContainsFilter(contains, ID_GETTER)
fun contains(s: String) = StringContainsFilter(s, ID_GETTER)
fun contains(regex: NativeRegExp) = StringContainsFilter(regex, ID_GETTER)
fun matches(regex: String) = StringMatchesFilter(regex, ID_GETTER)
fun matches(s: String) = StringMatchesFilter(s, ID_GETTER)
fun matches(regex: NativeRegExp) = StringMatchesFilter(regex, ID_GETTER)
fun match(regex: String) = StringMatchFilter(regex, ID_GETTER)
fun match(s: String) = StringMatchFilter(s, ID_GETTER)
fun match(regex: NativeRegExp) = StringMatchFilter(regex, ID_GETTER)
}

View File

@@ -0,0 +1,74 @@
package org.autojs.autojs.core.automator.filter
import java.util.regex.Pattern
internal object JsRegexUtils {
// Compile JavaScript regex literal "/pattern/flags" or plain pattern string to Kotlin Regex.
// zh-CN: 将 JavaScript 正则字面量 "/pattern/flags" 或普通模式字符串编译为 Kotlin 的 Regex.
fun compileJsOrPlainRegex(input: String): Regex {
parseJsRegexLiteral(input)?.let { (pattern, flags) ->
val javaFlags = toJavaPatternFlags(flags)
return Pattern.compile(pattern, javaFlags).toRegex()
}
return input.toRegex()
}
// Parse JavaScript regex literal by scanning delimiter '/' while respecting escapes and character classes.
// zh-CN: 通过扫描分隔符 '/' 解析 JavaScript 正则字面量, 同时处理转义与字符类.
fun parseJsRegexLiteral(input: String): Pair<String, String>? {
if (input.length < 2 || input[0] != '/') return null
var escaped = false
var inCharClass = false
for (i in 1 until input.length) {
val ch = input[i]
when {
escaped -> escaped = false
ch == '\\' -> escaped = true
ch == '[' -> inCharClass = true
ch == ']' && inCharClass -> inCharClass = false
ch == '/' && !inCharClass -> {
val pattern = input.substring(1, i)
val flags = input.substring(i + 1)
return pattern to flags
}
}
}
return null
}
// Map JavaScript flags to java.util.regex.Pattern flags. Unknown flags are ignored.
// zh-CN: 将 JavaScript flags 映射到 java.util.regex.Pattern flags, 未知 flags 将被忽略.
fun toJavaPatternFlags(flags: String): Int {
var f = 0
if (flags.contains('i')) f = f or Pattern.CASE_INSENSITIVE
if (flags.contains('m')) f = f or Pattern.MULTILINE
if (flags.contains('s')) f = f or Pattern.DOTALL
// Java "u" is not identical to JavaScript "u", but enabling Unicode-aware behavior is usually closer.
// zh-CN: Java 的 "u" 与 JavaScript 的 "u" 并不完全等价, 但开启 Unicode 相关行为通常更接近预期.
if (flags.contains('u')) {
f = f or Pattern.UNICODE_CASE
f = f or Pattern.UNICODE_CHARACTER_CLASS
}
// JavaScript "g/y" affects iteration/sticky behavior rather than "does it match", so it is ignored here.
// zh-CN: JavaScript 的 "g/y" 影响的是迭代/粘连行为, 而不是 "是否匹配", 因此这里忽略.
return f
}
// Format input regex as a JavaScript regex literal string for debugging display.
// zh-CN: 将输入正则格式化为 JavaScript 正则字面量字符串, 用于调试展示.
fun formatAsJsRegexLiteral(input: String): String {
val (pattern, flags) = parseJsRegexLiteral(input) ?: (input to "")
val safePattern = when (pattern.isEmpty()) {
true -> "(?:)"
else -> pattern.toRegex().toString().replace("/", "\\/")
}
return "/$safePattern/$flags"
}
}

View File

@@ -1,10 +1,11 @@
package org.autojs.autojs.core.automator.filter
import org.autojs.autojs.core.automator.UiObject
import org.mozilla.javascript.regexp.NativeRegExp
/**
* Created by Stardust on Mar 9, 2017.
* Modified by SuperMonster003 as of Nov 19, 2022.
* Modified by SuperMonster003 as of Dec 27, 2025.
*/
object PackageNameFilter {
@@ -16,16 +17,23 @@ object PackageNameFilter {
}
fun equals(text: String) = StringEqualsFilter(text, PACKAGE_NAME_GETTER)
@Suppress("CovariantEquals")
fun equals(s: String) = StringEqualsFilter(s, PACKAGE_NAME_GETTER)
fun contains(str: String) = StringContainsFilter(str, PACKAGE_NAME_GETTER)
@Suppress("CovariantEquals")
fun equals(regex: NativeRegExp) = StringEqualsFilter(regex, PACKAGE_NAME_GETTER)
fun contains(s: String) = StringContainsFilter(s, PACKAGE_NAME_GETTER)
fun contains(regex: NativeRegExp) = StringContainsFilter(regex, PACKAGE_NAME_GETTER)
fun startsWith(prefix: String) = StringStartsWithFilter(prefix, PACKAGE_NAME_GETTER)
fun endsWith(suffix: String) = StringEndsWithFilter(suffix, PACKAGE_NAME_GETTER)
fun matches(regex: String) = StringMatchesFilter(regex, PACKAGE_NAME_GETTER)
fun matches(s: String) = StringMatchesFilter(s, PACKAGE_NAME_GETTER)
fun matches(regex: NativeRegExp) = StringMatchesFilter(regex, PACKAGE_NAME_GETTER)
fun match(regex: String) = StringMatchFilter(regex, PACKAGE_NAME_GETTER)
fun match(s: String) = StringMatchFilter(s, PACKAGE_NAME_GETTER)
fun match(regex: NativeRegExp) = StringMatchFilter(regex, PACKAGE_NAME_GETTER)
}

View File

@@ -0,0 +1,35 @@
package org.autojs.autojs.core.automator.filter
import org.autojs.autojs.util.StringUtils.uppercaseFirstChar
import org.mozilla.javascript.regexp.NativeRegExp
/**
* Created by SuperMonster003 on Dec 27, 2025.
*/
abstract class RegexFilter(s: String, keyGetter: KeyGetter) : Filter {
open val actionName: String = ""
protected val input = s
protected val keyGetter = keyGetter
protected var isRegexSource = false
private set
// Compile regex only once to avoid repeated compilation during tree traversal.
// zh-CN: 仅编译一次正则, 避免在遍历节点树时重复编译带来的开销.
protected val compiledRegex by lazy(LazyThreadSafetyMode.NONE) { JsRegexUtils.compileJsOrPlainRegex(input) }
constructor(regex: NativeRegExp, keyGetter: KeyGetter) : this(regex.toString(), keyGetter) {
isRegexSource = true
}
override fun toString(): String {
val literal = when {
isRegexSource -> JsRegexUtils.formatAsJsRegexLiteral(input)
else -> "\"$input\""
}
return "${keyGetter}${actionName.uppercaseFirstChar()}($literal)"
}
}

View File

@@ -0,0 +1,35 @@
package org.autojs.autojs.core.automator.filter
import org.autojs.autojs.util.StringUtils.uppercaseFirstChar
import org.mozilla.javascript.regexp.NativeRegExp
/**
* Created by SuperMonster003 on Dec 27, 2025.
*/
abstract class RegexListFilter(s: String, keysGetter: KeysGetter) : Filter {
open val actionName: String = ""
protected val input = s
protected val keysGetter = keysGetter
protected var isRegexSource = false
private set
// Compile regex only once to avoid repeated compilation during tree traversal.
// zh-CN: 仅编译一次正则, 避免在遍历节点树时重复编译带来的开销.
protected val compiledRegex by lazy(LazyThreadSafetyMode.NONE) { JsRegexUtils.compileJsOrPlainRegex(input) }
constructor(regex: NativeRegExp, keysGetter: KeysGetter) : this(regex.toString(), keysGetter) {
isRegexSource = true
}
override fun toString(): String {
val literal = when {
isRegexSource -> JsRegexUtils.formatAsJsRegexLiteral(input)
else -> "\"$input\""
}
return "${keysGetter}${actionName.uppercaseFirstChar()}($literal)"
}
}

View File

@@ -1,15 +1,19 @@
package org.autojs.autojs.core.automator.filter
import org.autojs.autojs.core.automator.UiObject
import org.mozilla.javascript.regexp.NativeRegExp
/**
* Created by Stardust on Mar 9, 2017.
* Modified by SuperMonster003 as of Nov 19, 2022.
* Modified by SuperMonster003 as of Dec 27, 2025.
*/
class StringContainsFilter internal constructor(private val mContains: String, private val mKeyGetter: KeyGetter) : Filter {
class StringContainsFilter : RegexFilter {
override fun filter(node: UiObject) = mKeyGetter.getKey(node)?.contains(mContains) ?: false
override val actionName = "contains"
override fun toString() = "${mKeyGetter}Contains(\"$mContains\")"
constructor(s: String, keyGetter: KeyGetter) : super(s, keyGetter)
constructor(regex: NativeRegExp, keyGetter: KeyGetter) : super(regex, keyGetter)
override fun filter(node: UiObject) = keyGetter.getKey(node)?.contains(compiledRegex) == true
}

View File

@@ -1,15 +1,20 @@
package org.autojs.autojs.core.automator.filter
import org.autojs.autojs.core.automator.UiObject
import org.mozilla.javascript.regexp.NativeRegExp
/**
* Created by Stardust on Mar 9, 2017.
* Modified by SuperMonster003 as of Nov 19, 2022.
* Modified by SuperMonster003 as of Dec 27, 2025.
*/
class StringEqualsFilter(private val mValue: String, private val mKeyGetter: KeyGetter) : Filter {
class StringEqualsFilter : RegexFilter {
override fun filter(node: UiObject) = mKeyGetter.getKey(node)?.let { it == mValue } ?: false
constructor(s: String, keyGetter: KeyGetter) : super(s, keyGetter)
constructor(regex: NativeRegExp, keyGetter: KeyGetter) : super(regex, keyGetter)
override fun toString() = "$mKeyGetter(\"$mValue\")"
override fun filter(node: UiObject) = when {
isRegexSource -> keyGetter.getKey(node)?.matches(compiledRegex) == true
else -> keyGetter.getKey(node)?.contentEquals(input) == true
}
}

View File

@@ -1,14 +1,21 @@
package org.autojs.autojs.core.automator.filter
import org.autojs.autojs.core.automator.UiObject
import org.mozilla.javascript.regexp.NativeRegExp
/**
* Created by SuperMonster003 on Jun 10, 2022.
* Modified by SuperMonster003 as of Dec 27, 2025.
*/
class StringListContainsFilter internal constructor(private val mContains: String, private val mKeysGetter: KeysGetter) : Filter {
class StringListContainsFilter : RegexListFilter {
override fun filter(node: UiObject) = mKeysGetter.getKeys(node).any { it?.contains(mContains) ?: false }
override val actionName = "contains"
override fun toString() = "${mKeysGetter}Contains(\"$mContains\")"
constructor(s: String, keysGetter: KeysGetter) : super(s, keysGetter)
constructor(regex: NativeRegExp, keysGetter: KeysGetter) : super(regex, keysGetter)
override fun filter(node: UiObject) = keysGetter.getKeys(node).any {
it?.contains(compiledRegex) == true
}
}

View File

@@ -1,14 +1,23 @@
package org.autojs.autojs.core.automator.filter
import org.autojs.autojs.core.automator.UiObject
import org.mozilla.javascript.regexp.NativeRegExp
/**
* Created by SuperMonster003 on Jun 10, 2022.
* Modified by SuperMonster003 as of Dec 27, 2025.
*/
class StringListEqualsFilter(private val mValue: String, private val mKeysGetter: KeysGetter) : Filter {
class StringListEqualsFilter : RegexListFilter {
override fun filter(node: UiObject) = mKeysGetter.getKeys(node).any { it.contentEquals(mValue) }
override fun toString() = "$mKeysGetter(\"$mValue\")"
constructor(s: String, keysGetter: KeysGetter) : super(s, keysGetter)
constructor(regex: NativeRegExp, keysGetter: KeysGetter) : super(regex, keysGetter)
override fun filter(node: UiObject) = when {
isRegexSource -> keysGetter.getKeys(node).any {
it?.matches(compiledRegex) == true
}
else -> keysGetter.getKeys(node).any {
it?.contentEquals(input) == true
}
}
}

View File

@@ -1,36 +1,21 @@
package org.autojs.autojs.core.automator.filter
import org.autojs.autojs.core.automator.UiObject
import org.mozilla.javascript.regexp.NativeRegExp
/**
* Created by SuperMonster003 on Oct 17, 2022.
* Modified by SuperMonster003 as of Dec 27, 2025.
*/
class StringListMatchFilter internal constructor(private val mRegex: String, private val mKeysGetter: KeysGetter) : Filter {
class StringListMatchFilter : RegexListFilter {
// @Hint by SuperMonster003 on Oct 17, 2022.
// ! Similar to JavaScript "String.prototype.match"
// ! which returns the result of matching a string against a regular expression.
// ! https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/match
// ! https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/-regex/contains-match-in.html
// ! https://stackoverflow.com/questions/21883629/difference-in-results-between-java-matches-vs-javascript-match
// ! zh-CN:
// ! 与 JavaScript 的方法 "String.prototype.match" 类似,
// ! 它返回字符串与正则表达式匹配的结果.
// ! 参考链接见上.
override fun filter(node: UiObject) = mKeysGetter.getKeys(node).any {
it ?: return@any false
val prefix = "/"
val suffix = "/i"
if (mRegex.startsWith(prefix) && mRegex.endsWith(suffix)) {
mRegex
.slice(prefix.length until mRegex.length - suffix.length)
.toRegex(RegexOption.IGNORE_CASE)
.containsMatchIn(it)
} else {
mRegex.toRegex().containsMatchIn(it)
}
override val actionName = "match"
constructor(s: String, keysGetter: KeysGetter) : super(s, keysGetter)
constructor(regex: NativeRegExp, keysGetter: KeysGetter) : super(regex, keysGetter)
override fun filter(node: UiObject) = keysGetter.getKeys(node).any {
it?.contains(compiledRegex) == true
}
override fun toString() = "${mKeysGetter}Match(\"$mRegex\")"
}

View File

@@ -1,24 +1,21 @@
package org.autojs.autojs.core.automator.filter
import org.autojs.autojs.core.automator.UiObject
import org.mozilla.javascript.regexp.NativeRegExp
/**
* Created by SuperMonster003 on Jun 10, 2022.
* Modified by SuperMonster003 as of Dec 27, 2025.
*/
class StringListMatchesFilter internal constructor(private val mRegex: String, private val mKeysGetter: KeysGetter) : Filter {
class StringListMatchesFilter : RegexListFilter {
// @Hint by SuperMonster003 on Oct 17, 2022.
// ! Kotlin method "CharSequence.matches(regex: Regex): Boolean"
// ! indicates whether the regular expression matches the ENTIRE input (not partial input).
// ! https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/matches.html
// ! https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/-regex/matches.html
// ! https://stackoverflow.com/questions/21883629/difference-in-results-between-java-matches-vs-javascript-match
// ! zh-CN:
// ! Kotlin 的方法 "CharSequence.matches(regex: Regex): Boolean"
// ! 表示正则表达式是否完全匹配输入 (注意是完全而非部分匹配).
// ! 参考链接见上.
override fun filter(node: UiObject) = mKeysGetter.getKeys(node).any { it?.matches(mRegex.toRegex()) ?: false }
override val actionName = "matches"
override fun toString() = "${mKeysGetter}Matches(\"$mRegex\")"
constructor(s: String, keysGetter: KeysGetter) : super(s, keysGetter)
constructor(regex: NativeRegExp, keysGetter: KeysGetter) : super(regex, keysGetter)
override fun filter(node: UiObject) = keysGetter.getKeys(node).any {
it?.matches(compiledRegex) == true
}
}

View File

@@ -1,31 +1,19 @@
package org.autojs.autojs.core.automator.filter
import org.autojs.autojs.core.automator.UiObject
import org.mozilla.javascript.regexp.NativeRegExp
/**
* Created by Stardust on Mar 9, 2017.
* Modified by SuperMonster003 as of Nov 19, 2022.
* Modified by SuperMonster003 as of Dec 27, 2025.
*/
class StringMatchFilter internal constructor(private val mRegex: String, private val mKeyGetter: KeyGetter) : Filter {
class StringMatchFilter : RegexFilter {
// @Hint by SuperMonster003 on Oct 17, 2022.
// ! Similar to JavaScript "String.prototype.match"
// ! which returns the result of matching a string against a regular expression.
// ! https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/match
// ! https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/-regex/contains-match-in.html
// ! https://stackoverflow.com/questions/21883629/difference-in-results-between-java-matches-vs-javascript-match
// ! zh-CN:
// ! 与 JavaScript 的方法 "String.prototype.match" 类似,
// ! 它返回字符串与正则表达式匹配的结果.
// ! 参考链接见上.
override fun filter(node: UiObject) = mKeyGetter.getKey(node)?.contains(mRegex.toRegex()) ?: false
override val actionName = "match"
override fun toString(): String {
val regexStr = when (mRegex.isEmpty()) {
true -> "(?:)"
else -> mRegex.toRegex().toString().replace("/", "\\/")
}
return "${mKeyGetter}Match(/$regexStr/)"
}
constructor(s: String, keyGetter: KeyGetter) : super(s, keyGetter)
constructor(regex: NativeRegExp, keyGetter: KeyGetter) : super(regex, keyGetter)
override fun filter(node: UiObject) = keyGetter.getKey(node)?.contains(compiledRegex) == true
}

View File

@@ -1,30 +1,19 @@
package org.autojs.autojs.core.automator.filter
import org.autojs.autojs.core.automator.UiObject
import org.mozilla.javascript.regexp.NativeRegExp
/**
* Created by Stardust on Mar 9, 2017.
* Modified by SuperMonster003 as of Dec 27, 2025.
*/
class StringMatchesFilter internal constructor(private val mRegex: String, private val mKeyGetter: KeyGetter) : Filter {
open class StringMatchesFilter : RegexFilter {
// @Hint by SuperMonster003 on Oct 17, 2022.
// ! Kotlin method "CharSequence.matches(regex: Regex): Boolean"
// ! indicates whether the regular expression matches the ENTIRE input (not partial input).
// ! https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/matches.html
// ! https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/-regex/matches.html
// ! https://stackoverflow.com/questions/21883629/difference-in-results-between-java-matches-vs-javascript-match
// ! zh-CN:
// ! Kotlin 的方法 "CharSequence.matches(regex: Regex): Boolean"
// ! 表示正则表达式是否完全匹配输入 (注意是完全而非部分匹配).
// ! 参考链接见上.
override fun filter(node: UiObject) = mKeyGetter.getKey(node)?.matches(mRegex.toRegex()) ?: false
override val actionName = "matches"
override fun toString(): String {
val regexStr = when (mRegex.isEmpty()) {
true -> "(?:)"
else -> mRegex.toRegex().toString().replace("/", "\\/")
}
return "${mKeyGetter}Matches(/$regexStr/)"
}
constructor(s: String, keyGetter: KeyGetter) : super(s, keyGetter)
constructor(regex: NativeRegExp, keyGetter: KeyGetter) : super(regex, keyGetter)
override fun filter(node: UiObject) = keyGetter.getKey(node)?.matches(compiledRegex) == true
}

View File

@@ -1,10 +1,11 @@
package org.autojs.autojs.core.automator.filter
import org.autojs.autojs.core.automator.UiObject
import org.mozilla.javascript.regexp.NativeRegExp
/**
* Created by Stardust on Mar 9, 2017.
* Modified by SuperMonster003 as of Nov 19, 2022.
* Modified by SuperMonster003 as of Dec 27, 2025.
*/
object TextFilter {
@@ -16,16 +17,23 @@ object TextFilter {
}
fun equals(text: String) = StringEqualsFilter(text, TEXT_GETTER)
@Suppress("CovariantEquals")
fun equals(s: String) = StringEqualsFilter(s, TEXT_GETTER)
fun contains(str: String) = StringContainsFilter(str, TEXT_GETTER)
@Suppress("CovariantEquals")
fun equals(regex: NativeRegExp) = StringEqualsFilter(regex, TEXT_GETTER)
fun contains(s: String) = StringContainsFilter(s, TEXT_GETTER)
fun contains(regex: NativeRegExp) = StringContainsFilter(regex, TEXT_GETTER)
fun startsWith(prefix: String) = StringStartsWithFilter(prefix, TEXT_GETTER)
fun endsWith(suffix: String) = StringEndsWithFilter(suffix, TEXT_GETTER)
fun matches(regex: String) = StringMatchesFilter(regex, TEXT_GETTER)
fun matches(s: String) = StringMatchesFilter(s, TEXT_GETTER)
fun matches(regex: NativeRegExp) = StringMatchesFilter(regex, TEXT_GETTER)
fun match(regex: String) = StringMatchFilter(regex, TEXT_GETTER)
fun match(s: String) = StringMatchFilter(s, TEXT_GETTER)
fun match(regex: NativeRegExp) = StringMatchFilter(regex, TEXT_GETTER)
}

View File

@@ -66,7 +66,7 @@ abstract class Augmentable(private val scriptRuntime: ScriptRuntime? = null) : F
open val key: String
get() = when {
mIsOriginalKeyName -> javaClass.simpleName
else -> lowercaseFirstChar(javaClass.simpleName)
else -> javaClass.simpleName.lowercaseFirstChar()
}
/**

View File

@@ -30,11 +30,11 @@ open class AugmentableProxy(private val scriptRuntime: ScriptRuntime) : Augmenta
val setterResult = listOf(
when {
Regex("^set[A-Z].*").containsMatchIn(key) -> key
else -> "set${uppercaseFirstChar(key)}"
else -> "set${key.uppercaseFirstChar()}"
},
when {
Regex("^is[A-Z].*").containsMatchIn(key) -> key
else -> "is${uppercaseFirstChar(key)}"
else -> "is${key.uppercaseFirstChar()}"
},
).any { setCore(augmented, it, value) }
@@ -62,8 +62,8 @@ open class AugmentableProxy(private val scriptRuntime: ScriptRuntime) : Augmenta
open fun get(augmented: ScriptableObject, key: String): Any? {
listOf(
key,
"get${uppercaseFirstChar(key)}",
"is${uppercaseFirstChar(key)}",
"get${key.uppercaseFirstChar()}",
"is${key.uppercaseFirstChar()}",
).forEach {
getCore(augmented, it).let { result ->
if (result != NOT_FOUND) return result

View File

@@ -55,7 +55,7 @@ class ColorNativeObject @JvmOverloads constructor(color: Any? = BLACK) : NativeO
return when (name) {
"equals", StringReadable.KEY -> true
in mProxySetterNames -> true
in mProxyTowardsNames.map { "to${uppercaseFirstChar(it)}" } -> true
in mProxyTowardsNames.map { "to${it.uppercaseFirstChar()}" } -> true
else -> super.has(name, start)
}
}
@@ -80,7 +80,7 @@ class ColorNativeObject @JvmOverloads constructor(color: Any? = BLACK) : NativeO
}
else -> {
val protoName = when (name) {
in mProxyTowardsNames -> "to${uppercaseFirstChar(name)}"
in mProxyTowardsNames -> "to${name.uppercaseFirstChar()}"
else -> name
}
try {

View File

@@ -220,14 +220,14 @@ class Console(scriptRuntime: ScriptRuntime) : AugmentableProxy(scriptRuntime) {
@JvmStatic
@RhinoRuntimeFunctionInterface
fun input(scriptRuntime: ScriptRuntime, args: Array<out Any?>) {
val s = "${lowercaseFirstChar(Console::class.java.simpleName)}.${::input.name}"
val s = "${Console::class.java.simpleName.lowercaseFirstChar()}.${::input.name}"
throw RuntimeException(globalContext.getString(R.string.error_abandoned_method, s))
}
@JvmStatic
@RhinoRuntimeFunctionInterface
fun rawInput(scriptRuntime: ScriptRuntime, args: Array<out Any?>) {
val s = "${lowercaseFirstChar(Console::class.java.simpleName)}.${::rawInput.name}"
val s = "${Console::class.java.simpleName.lowercaseFirstChar()}.${::rawInput.name}"
throw RuntimeException(globalContext.getString(R.string.error_abandoned_method, s))
}
@@ -311,11 +311,11 @@ class Console(scriptRuntime: ScriptRuntime) : AugmentableProxy(scriptRuntime) {
val fName = listOf(
when {
Regex("^set[A-Z].*").containsMatchIn(key) -> key
else -> "set${uppercaseFirstChar(key)}"
else -> "set${key.uppercaseFirstChar()}"
},
when {
Regex("^is[A-Z].*").containsMatchIn(key) -> key
else -> "is${uppercaseFirstChar(key)}"
else -> "is${key.uppercaseFirstChar()}"
},
).find { name ->
configurator::class.java.methods.any { method -> method.name == name }

View File

@@ -15,6 +15,10 @@ import org.autojs.autojs.extension.AnyExtensions.isJsXml
import org.autojs.autojs.extension.AnyExtensions.jsBrief
import org.autojs.autojs.extension.AnyExtensions.jsUnwrapped
import org.autojs.autojs.extension.ArrayExtensions.toNativeArray
import org.autojs.autojs.extension.FlexibleArray.Companion.component1
import org.autojs.autojs.extension.FlexibleArray.Companion.component2
import org.autojs.autojs.extension.FlexibleArray.Companion.component3
import org.autojs.autojs.extension.FlexibleArray.Companion.component4
import org.autojs.autojs.extension.ScriptableExtensions.defineProp
import org.autojs.autojs.extension.ScriptableExtensions.prop
import org.autojs.autojs.extension.ScriptableObjectExtensions.inquire
@@ -36,7 +40,7 @@ import org.autojs.autojs.util.RhinoUtils.isUiThread
import org.autojs.autojs.util.RhinoUtils.js_eval
import org.autojs.autojs.util.RhinoUtils.newBaseFunction
import org.autojs.autojs.util.RhinoUtils.newNativeObject
import org.autojs.autojs.util.StringUtils
import org.autojs.autojs.util.StringUtils.uppercaseFirstChar
import org.autojs.autojs6.R
import org.mozilla.javascript.BaseFunction
import org.mozilla.javascript.Context
@@ -672,7 +676,7 @@ class Dialogs(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
if (animation == "default") {
win.setWindowAnimations(android.R.style.Animation)
} else {
val suffix = StringUtils.uppercaseFirstChar(animation.replace('-', '_'))
val suffix = animation.replace('-', '_').uppercaseFirstChar()
val animationStyle = android.R.style::class.java.getDeclaredField("Animation_$suffix").getInt(null)
win.setWindowAnimations(animationStyle)
}

View File

@@ -11,13 +11,13 @@ import org.autojs.autojs.runtime.exception.WrappedIllegalArgumentException
import org.autojs.autojs.util.RhinoUtils.UNDEFINED
import org.autojs.autojs.util.RhinoUtils.coerceString
import org.autojs.autojs.util.RhinoUtils.flatten
import org.autojs.autojs.util.StringUtils
import org.autojs.autojs.util.StringUtils.lowercaseFirstChar
import org.autojs.autojs.util.StringUtils.uppercaseFirstChar
import org.mozilla.javascript.Undefined
class Jsox(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime), Invokable {
override val key = lowercaseFirstChar(javaClass.simpleName)
override val key = javaClass.simpleName.lowercaseFirstChar()
override val selfAssignmentFunctions = listOf(
::extend.name,
@@ -73,7 +73,7 @@ class Jsox(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime
fun extendAllRhinoWithRuntime(scriptRuntime: ScriptRuntime): Undefined = extendRhinoWithRuntime(scriptRuntime, presetModules)
private fun normalizeModuleName(name: String): String {
return StringUtils.uppercaseFirstChar(if (!name.endsWith('x')) "${name}x" else name)
return "${name.removeSuffix("x")}x".uppercaseFirstChar()
}
}

View File

@@ -12,7 +12,6 @@ import org.autojs.autojs.util.AndroidUtils.SystemProperties
import org.autojs.autojs.util.RhinoUtils.coerceBoolean
import org.autojs.autojs.util.RhinoUtils.coerceIntNumber
import org.autojs.autojs.util.RhinoUtils.coerceString
import org.autojs.autojs.util.StringUtils.convertRegex
import org.mozilla.javascript.NativeObject
import org.mozilla.javascript.regexp.NativeRegExp
@@ -85,7 +84,7 @@ class SysProps(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime), Invok
private fun matchFilter(input: String, filter: Any?) = when {
filter.isJsNullish() -> true
filter is NativeRegExp -> Regex(convertRegex(filter.toString())).containsMatchIn(input)
filter is NativeRegExp -> filter.toString().toRegex().containsMatchIn(input)
else -> input.contains(coerceString(filter))
}

View File

@@ -91,7 +91,6 @@ object IntentUtils {
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.let { context.startActivity(it) }
}
} catch (e: ActivityNotFoundException) {
exceptionHolder?.show(R.string.error_no_applications_available_for_browsing_this_link)
// ViewUtils.showToast(context, R.string.text_no_browser, true)

View File

@@ -11,7 +11,7 @@ import org.autojs.autojs.extension.NumberExtensions.roundToString
import org.opencv.core.Point
import java.nio.charset.Charset
import java.nio.charset.StandardCharsets
import java.util.Locale
import java.util.*
import kotlin.math.min
import kotlin.math.pow
@@ -21,8 +21,6 @@ import kotlin.math.pow
*/
object StringUtils {
private val regexPattern = "^/(.+)/$".toRegex()
private val globalAppContext by lazy { GlobalAppContext.get() }
private val localePref = mapOf(
@@ -39,22 +37,6 @@ object StringUtils {
@JvmStatic
fun key(@LocaleNonRelated resId: Int): String = globalAppContext.getString(resId)
// @Overwrite by SuperMonster003 on May 5, 2022.
// ! Dunno what "better implementation" really means.
// ! The only thing I did was make code more "lightweight". ;)
// ! zh-CN:
// ! 不清楚 "更好的实现方式" 的真正含义.
// ! 唯一做的只是使代码更 "轻量级". [眨眼符号]
// @TodoDiary by Stardust on Jan 30, 2018.
// ! 更好的实现方式.
// ! en-US (translated by SuperMonster003 on Jul 29, 2024):
// ! Better implementation.
@JvmStatic
fun convertRegex(regex: String) = regex.apply { if (shouldTakenAsRegex(this)) return replace(regexPattern, "$1") }
@JvmStatic
fun shouldTakenAsRegex(s: String) = regexPattern.containsMatchIn(s)
@JvmStatic
fun join(delimiter: CharSequence?, vararg tokens: Any?): String = TextUtils.join(delimiter!!, tokens)
@@ -209,14 +191,20 @@ object StringUtils {
}
@JvmStatic
fun uppercaseFirstChar(s: String) = if (s.isEmpty()) s else s.replaceFirstChar { s[0].uppercaseChar() }
fun String.uppercaseFirstChar(): String {
val s = this
return if (s.isEmpty()) s else s.replaceFirstChar { s[0].uppercaseChar() }
}
@JvmStatic
fun lowercaseFirstChar(s: String) = if (s.isEmpty()) s else s.replaceFirstChar { s[0].lowercaseChar() }
fun String.lowercaseFirstChar(): String {
val s = this
return if (s.isEmpty()) s else s.replaceFirstChar { s[0].lowercaseChar() }
}
@JvmStatic
@Deprecated("Deprecated since v6.6.0", ReplaceWith("uppercaseFirstChar(s)"))
fun toUpperCaseFirst(s: String) = uppercaseFirstChar(s)
fun toUpperCaseFirst(s: String) = s.uppercaseFirstChar()
@JvmStatic
fun toFormattedSummary(dataList: List<Pair<String, () -> Any?>>): String {

View File

@@ -1,5 +1,5 @@
#Sat Dec 27 13:20:38 CST 2025
BUILD_TIME=1766812838968
#Sat Dec 27 21:41:16 CST 2025
BUILD_TIME=1766842876384
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=3554
VERSION_BUILD=3557
VERSION_NAME=6.7.0 Alpha13
VSCODE_EXT_REQUIRED_VERSION=1.0.8