6.6.1 - Alpha2 - 增加 UiObject#isSimilar 及 UiObjectCollection#isSimilar 方法
This commit is contained in:
@@ -1,19 +1,22 @@
|
||||
{
|
||||
"$data": {
|
||||
"v6.6.1": {
|
||||
"released_date": "2024/12/08",
|
||||
"released_date": "2024/12/09",
|
||||
"feature": [
|
||||
"pinyin 模块, 用于汉语拼音转换 (参阅 项目文档 > [汉语拼音](https://docs.autojs6.com/#/pinyin))"
|
||||
"pinyin 模块, 用于汉语拼音转换 (参阅 项目文档 > [汉语拼音](https://docs.autojs6.com/#/pinyin))",
|
||||
"UiObject#isSimilar 及 UiObjectCollection#isSimilar 方法, 用于确定控件或控件集合是否相似"
|
||||
],
|
||||
"fix": [
|
||||
"部分环境因回退版本过低而无法正常编译项目的问题",
|
||||
"调用不存在的方法时可能出现的 \"非原始类型值\" 异常",
|
||||
"部分设备无法正常添加脚本快捷方式的问题 (试修) _[`issue #221`](http://issues.autojs6.com/221)_",
|
||||
"automator.click/longClick 方法参数类型限制错误 _[`issue #275`](http://issues.autojs6.com/275)_"
|
||||
"automator.click/longClick 方法参数类型限制错误 _[`issue #275`](http://issues.autojs6.com/275)_",
|
||||
"UiObjectCollection 实例缺失自身方法及属性的问题"
|
||||
],
|
||||
"improvement": [
|
||||
"脚本项目识别在 project.json 损坏情况下尽可能还原关键信息",
|
||||
"打包单文件时自动生成的包名后缀支持将简体中文自动转换为拼音",
|
||||
"UiSelector#findOnce 及 UiSelector#find 方法支持负数参数",
|
||||
"UI 元素及 className 相关选择器支持更多的包名前缀省略形式 (如 RecyclerView, Snackbar 等)"
|
||||
]
|
||||
},
|
||||
|
||||
@@ -13,6 +13,7 @@ import org.autojs.autojs.core.accessibility.AccessibilityNodeInfoHelper
|
||||
import org.autojs.autojs.core.accessibility.UiSelector
|
||||
import org.autojs.autojs.extension.AnyExtensions.isJsNullish
|
||||
import org.autojs.autojs.extension.AnyExtensions.isJsUndefined
|
||||
import org.autojs.autojs.extension.ArrayExtensions.toHashCode
|
||||
import org.autojs.autojs.extension.ArrayExtensions.toNativeArray
|
||||
import org.autojs.autojs.runtime.ScriptRuntime
|
||||
import org.autojs.autojs.util.DisplayUtils.toRoundIntX
|
||||
@@ -22,6 +23,7 @@ import org.autojs.autojs.util.StringUtils.str
|
||||
import org.autojs.autojs6.R
|
||||
import org.mozilla.javascript.BaseFunction
|
||||
import org.mozilla.javascript.Context
|
||||
import org.mozilla.javascript.Scriptable
|
||||
import org.opencv.core.Point
|
||||
import org.opencv.core.Size
|
||||
import kotlin.math.roundToInt
|
||||
@@ -485,8 +487,109 @@ open class UiObject(
|
||||
|
||||
override fun toString() = "[${UiObject::class.java.simpleName}] $className ${summary()}"
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return super.hashCode()
|
||||
override fun hashCode() = listOf(
|
||||
"${packageName()}",
|
||||
"$parent",
|
||||
"${id()}",
|
||||
"${fullId()}",
|
||||
"${idHex()}",
|
||||
"${desc()}",
|
||||
text(),
|
||||
"${bounds()}",
|
||||
"${className()}",
|
||||
"${clickable()}",
|
||||
"${longClickable()}",
|
||||
"${scrollable()}",
|
||||
"${indexInParent()}",
|
||||
"${childCount()}",
|
||||
"${depth()}",
|
||||
"${checked()}",
|
||||
"${enabled()}",
|
||||
"${editable()}",
|
||||
"${focusable()}",
|
||||
"${checkable()}",
|
||||
"${selected()}",
|
||||
"$isDismissable",
|
||||
"${visibleToUser()}",
|
||||
"$isContextClickable",
|
||||
"${focused()}",
|
||||
"$isAccessibilityFocused",
|
||||
"${rowCount()}",
|
||||
"${columnCount()}",
|
||||
"${row()}",
|
||||
"${column()}",
|
||||
"${rowSpan()}",
|
||||
"${columnSpan()}",
|
||||
"$drawingOrder",
|
||||
"${actionNames()}",
|
||||
"${isSingleton()}",
|
||||
"${firstSibling()}",
|
||||
"${lastSibling()}",
|
||||
"${firstChild()}",
|
||||
"${lastChild()}",
|
||||
).toHashCode()
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other !is UiObject) return false
|
||||
|
||||
return packageName() == other.packageName() &&
|
||||
parent == other.parent &&
|
||||
id() == other.id() &&
|
||||
fullId() == other.fullId() &&
|
||||
idHex() == other.idHex() &&
|
||||
desc() == other.desc() &&
|
||||
text() == other.text() &&
|
||||
bounds() == other.bounds() &&
|
||||
className() == other.className() &&
|
||||
clickable() == other.clickable() &&
|
||||
longClickable() == other.longClickable() &&
|
||||
scrollable() == other.scrollable() &&
|
||||
indexInParent() == other.indexInParent() &&
|
||||
childCount() == other.childCount() &&
|
||||
depth() == other.depth() &&
|
||||
checked() == other.checked() &&
|
||||
enabled() == other.enabled() &&
|
||||
editable() == other.editable() &&
|
||||
focusable() == other.focusable() &&
|
||||
checkable() == other.checkable() &&
|
||||
selected() == other.selected() &&
|
||||
isDismissable == other.isDismissable &&
|
||||
visibleToUser() == other.visibleToUser() &&
|
||||
isContextClickable == other.isContextClickable &&
|
||||
focused() == other.focused() &&
|
||||
isAccessibilityFocused == other.isAccessibilityFocused &&
|
||||
rowCount() == other.rowCount() &&
|
||||
columnCount() == other.columnCount() &&
|
||||
row() == other.row() &&
|
||||
column() == other.column() &&
|
||||
rowSpan() == other.rowSpan() &&
|
||||
columnSpan() == other.columnSpan() &&
|
||||
drawingOrder == other.drawingOrder &&
|
||||
actionNames() == other.actionNames() &&
|
||||
isSingleton() == other.isSingleton() &&
|
||||
"${firstSibling()}" == "${other.firstSibling()}" &&
|
||||
"${lastSibling()}" == "${other.lastSibling()}" &&
|
||||
"${firstChild()}" == "${other.firstChild()}" &&
|
||||
"${lastChild()}" == "${other.lastChild()}"
|
||||
}
|
||||
|
||||
fun isSimilar(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other == null) return false
|
||||
when (other) {
|
||||
is Scriptable -> {
|
||||
val thisHashCode = hashCode()
|
||||
val otherHashCode = RhinoUtils.hashCodeOfScriptable(other) ?: return false
|
||||
return thisHashCode == otherHashCode
|
||||
}
|
||||
else -> {
|
||||
return when {
|
||||
other.javaClass != UiObject::class.java -> false
|
||||
else -> hashCode() == other.hashCode()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
@@ -496,14 +599,7 @@ open class UiObject(
|
||||
internal const val RESULT_TYPE_WIDGET = "widget"
|
||||
|
||||
private val RESULT_GROUP_WIDGET by lazy { arrayOf("#", "w", RESULT_TYPE_WIDGET) }
|
||||
private val RESULT_GROUP_WIDGET_COLLECTION by lazy {
|
||||
arrayOf("{}", "wc", "collection", "list").plus(
|
||||
listAliases(
|
||||
"#",
|
||||
"w"
|
||||
)
|
||||
)
|
||||
}
|
||||
private val RESULT_GROUP_WIDGET_COLLECTION by lazy { arrayOf("{}", "wc", "collection", "list").plus(listAliases("#", "w")) }
|
||||
private val RESULT_GROUP_WIDGETS by lazy { arrayOf("[]", "ws", "widgets").plus(arrayAliases("#", "w")) }
|
||||
private val RESULT_GROUP_CONTENT by lazy { arrayOf("$", "txt", "content") }
|
||||
private val RESULT_GROUP_CONTENTS by lazy { arrayOf("contents").plus(arrayAliases("$", "txt", "content")) }
|
||||
@@ -520,9 +616,8 @@ open class UiObject(
|
||||
@JvmStatic
|
||||
@Throws(IllegalArgumentException::class)
|
||||
fun ensureCompass(s: CharSequence?) {
|
||||
if (s != null && !isCompass(s)) {
|
||||
throw IllegalArgumentException(str(R.string.error_invalid_compass, s))
|
||||
}
|
||||
s ?: return
|
||||
require(isCompass(s)) { str(R.string.error_invalid_compass, s) }
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
package org.autojs.autojs.core.automator
|
||||
|
||||
import org.autojs.autojs.core.accessibility.UiSelector
|
||||
import org.autojs.autojs.extension.ArrayExtensions.toHashCode
|
||||
import org.autojs.autojs.tool.Consumer
|
||||
import org.autojs.autojs.util.RhinoUtils
|
||||
import org.mozilla.javascript.Scriptable
|
||||
|
||||
/**
|
||||
* Created by Stardust on Mar 9, 2017.
|
||||
@@ -62,7 +65,36 @@ class UiObjectCollection private constructor(val nodes: List<UiObject?>) : UiObj
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "${UiObjectCollection::class.java.name}@${hashCode()}"
|
||||
return "${UiObjectCollection::class.java.name}@${super.hashCode()}"
|
||||
}
|
||||
|
||||
override fun hashCode(): Int = when {
|
||||
nodes.isEmpty() -> super.hashCode()
|
||||
else -> nodes.map { it.hashCode() }.toHashCode()
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other !is UiObjectCollection) return false
|
||||
return nodes == other.nodes
|
||||
}
|
||||
|
||||
fun isSimilar(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other == null) return false
|
||||
when (other) {
|
||||
is Scriptable -> {
|
||||
val thisHashCode = hashCode()
|
||||
val otherHashCode = RhinoUtils.hashCodeOfScriptable(other) ?: return false
|
||||
return thisHashCode == otherHashCode
|
||||
}
|
||||
else -> {
|
||||
return when {
|
||||
other.javaClass != UiObjectCollection::class.java -> false
|
||||
else -> hashCode() == other.hashCode()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -7,9 +7,11 @@ import android.os.Looper
|
||||
import android.os.Parcelable
|
||||
import android.util.Log
|
||||
import org.autojs.autojs.AutoJs
|
||||
import org.autojs.autojs.core.automator.UiObjectCollection
|
||||
import org.autojs.autojs.extension.AnyExtensions.isJsNullish
|
||||
import org.autojs.autojs.extension.AnyExtensions.jsBrief
|
||||
import org.autojs.autojs.extension.AnyExtensions.jsSpecies
|
||||
import org.autojs.autojs.extension.AnyExtensions.jsUnwrapped
|
||||
import org.autojs.autojs.extension.ScriptableExtensions.defineProp
|
||||
import org.autojs.autojs.extension.ScriptableExtensions.prop
|
||||
import org.autojs.autojs.rhino.TopLevelScope
|
||||
@@ -813,6 +815,22 @@ object RhinoUtils {
|
||||
@JvmStatic
|
||||
fun newNativeArray(array: Array<Any?>) = NativeArray(array).also { it.exportAsJSClass(NativeArray.MAX_PROTOTYPE_ID, it, false) }
|
||||
|
||||
@JvmStatic
|
||||
fun hashCodeOfScriptable(other: Any?): Int? {
|
||||
if (other !is Scriptable) return null
|
||||
val getClassFunc = other["getClass"]
|
||||
if (getClassFunc is BaseFunction) {
|
||||
val clazz = callFunction(getClassFunc, emptyArray()).jsUnwrapped()
|
||||
if (clazz != UiObjectCollection::class.java) return null
|
||||
}
|
||||
val hashCodeFunc = other["hashCode"]
|
||||
if (hashCodeFunc is BaseFunction) {
|
||||
val hashCode = callFunction(hashCodeFunc, emptyArray()).jsUnwrapped()
|
||||
if (hashCode is Number) return hashCode.toInt()
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
class ObsoletedRhinoFunctionException(funcName: String) : Exception(
|
||||
"Function \"$funcName\" can no longer be used as it has been obsoleted",
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user