diff --git a/app/src/main/assets/modules/__automator__.js b/app/src/main/assets/modules/__automator__.js index 8c058bd0..8ecdd496 100644 --- a/app/src/main/assets/modules/__automator__.js +++ b/app/src/main/assets/modules/__automator__.js @@ -61,6 +61,23 @@ module.exports = function (scriptRuntime, scope) { return util.java.toJsArray(a11yBridge.windowRoots(), false) .map(root => UiObject.createRoot(root)); }, + stateListener(listener) { + return a11yBridge.setAccessibilityListener(listener); + }, + registerEvent(name, listener) { + return rtAutomator.registerEvent(name, listener); + }, + /** @deprecated */ + registerEvents(name, listener) { + return rtAutomator.registerEvent(name, listener); + }, + removeEvent(name) { + return rtAutomator.removeEvent(name); + }, + /** @deprecated */ + removeEvents(name) { + return rtAutomator.removeEvent(name); + }, waitFor(timeout) { automator.waitForService(timeout); }, diff --git a/app/src/main/java/org/autojs/autojs/codegeneration/ReadOnlyUiObject.java b/app/src/main/java/org/autojs/autojs/codegeneration/ReadOnlyUiObject.java index 47b999f8..5634eadb 100644 --- a/app/src/main/java/org/autojs/autojs/codegeneration/ReadOnlyUiObject.java +++ b/app/src/main/java/org/autojs/autojs/codegeneration/ReadOnlyUiObject.java @@ -70,7 +70,7 @@ public class ReadOnlyUiObject extends UiObject { @Override public String id() { - return mNodeInfo.getSimpleId(); + return mNodeInfo.getId(); } @Override diff --git a/app/src/main/java/org/autojs/autojs/core/accessibility/AccessibilityBridge.java b/app/src/main/java/org/autojs/autojs/core/accessibility/AccessibilityBridge.java index 4f94580f..e49d5d29 100644 --- a/app/src/main/java/org/autojs/autojs/core/accessibility/AccessibilityBridge.java +++ b/app/src/main/java/org/autojs/autojs/core/accessibility/AccessibilityBridge.java @@ -150,4 +150,7 @@ public abstract class AccessibilityBridge { return mConfig; } + public void setAccessibilityListener(AccessibilityServiceCallback listener) { + AccessibilityService.Companion.setCallback(listener); + } } diff --git a/app/src/main/java/org/autojs/autojs/core/accessibility/AccessibilityService.kt b/app/src/main/java/org/autojs/autojs/core/accessibility/AccessibilityService.kt index 7c517f9f..2a412561 100644 --- a/app/src/main/java/org/autojs/autojs/core/accessibility/AccessibilityService.kt +++ b/app/src/main/java/org/autojs/autojs/core/accessibility/AccessibilityService.kt @@ -8,33 +8,57 @@ import android.view.accessibility.AccessibilityEvent import android.view.accessibility.AccessibilityEvent.TYPE_VIEW_FOCUSED import android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED import android.view.accessibility.AccessibilityNodeInfo +import org.autojs.autojs.core.accessibility.SimpleActionAutomator.Companion.AccessibilityEventCallback +import org.autojs.autojs.core.automator.AccessibilityEventWrapper import org.autojs.autojs.event.EventDispatcher import org.autojs.autojs.pref.Pref -import java.util.TreeMap +import java.util.* import java.util.concurrent.Executors import java.util.concurrent.TimeUnit import java.util.concurrent.locks.ReentrantLock +interface AccessibilityServiceCallback { + fun onConnected() + fun onDisconnected() +} /** * Created by Stardust on 2017/5/2. */ open class AccessibilityService : android.accessibilityservice.AccessibilityService() { - val onKeyObserver = OnKeyListener.Observer() val keyInterrupterObserver = KeyInterceptor.Observer() var fastRootInActiveWindow: AccessibilityNodeInfo? = null - var bridge: AccessibilityBridge? = null + private val eventBox = TreeMap() private val gestureEventDispatcher = EventDispatcher() private val eventExecutor by lazy { Executors.newSingleThreadExecutor() } - override fun onAccessibilityEvent(event: AccessibilityEvent) { - if (instance != this) { - instance = this + private fun eventNameToType(str: String): Int { + return try { + val sb = StringBuilder() + sb.append("TYPE_") + val upperCase = str.uppercase(Locale.getDefault()) + sb.append(upperCase) + AccessibilityEvent::class.java.getField(sb.toString()).get(null) as Int + } catch (unused: NoSuchFieldException) { + throw IllegalArgumentException("unknown event type: $str") } + } + + fun addAccessibilityEventCallback(name: String, callback: AccessibilityEventCallback) { + eventBox[eventNameToType(name)] = callback + } + + fun removeAccessibilityEventCallback(name: String) { + eventBox.remove(eventNameToType(name)) + } + + override fun onAccessibilityEvent(event: AccessibilityEvent) { + if (instance != this) instance = this val type = event.eventType + eventBox[type]?.onAccessibilityEvent(AccessibilityEventWrapper(event)) if (containsAllEventTypes || eventTypes.contains(type)) { if (type == TYPE_WINDOW_STATE_CHANGED || type == TYPE_VIEW_FOCUSED) { rootInActiveWindow?.also { fastRootInActiveWindow = it } @@ -86,12 +110,12 @@ open class AccessibilityService : android.accessibilityservice.AccessibilityServ instance = null bridge = null eventExecutor.shutdownNow() + callback?.onDisconnected() super.onDestroy() } override fun onServiceConnected() { instance = this - serviceInfo = serviceInfo.apply { AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS.let { flags = (if (Pref.isStableModeEnabled) flags and it.inv() else flags or it) @@ -102,7 +126,7 @@ open class AccessibilityService : android.accessibilityservice.AccessibilityServ } } } - + callback?.onConnected() super.onServiceConnected() LOCK.lock() @@ -122,6 +146,7 @@ open class AccessibilityService : android.accessibilityservice.AccessibilityServ private val LOCK = ReentrantLock() private val ENABLED = LOCK.newCondition() + private var callback: AccessibilityServiceCallback? = null var instance: AccessibilityService? = null private set @@ -141,6 +166,7 @@ open class AccessibilityService : android.accessibilityservice.AccessibilityServ fun isNotRunning() = !isRunning() fun addDelegate(uniquePriority: Int, delegate: AccessibilityDelegate) { + // 用于记录eventTypes中的事件id delegates[uniquePriority] = delegate val set = delegate.eventTypes if (set == null) { @@ -178,13 +204,16 @@ open class AccessibilityService : android.accessibilityservice.AccessibilityServ LOCK.unlock() } } - - interface GestureListener { - - fun onGesture(gestureId: Int) - + @JvmStatic + fun clearAccessibilityEventCallback() { + instance?.eventBox?.clear() + } + fun setCallback(listener: AccessibilityServiceCallback) { + callback = listener } + interface GestureListener { + fun onGesture(gestureId: Int) + } } - } diff --git a/app/src/main/java/org/autojs/autojs/core/accessibility/LayoutInspector.kt b/app/src/main/java/org/autojs/autojs/core/accessibility/LayoutInspector.kt index fb6d89c4..897a9149 100644 --- a/app/src/main/java/org/autojs/autojs/core/accessibility/LayoutInspector.kt +++ b/app/src/main/java/org/autojs/autojs/core/accessibility/LayoutInspector.kt @@ -61,8 +61,7 @@ class LayoutInspector(private val mContext: Context) { } private fun refreshChildList(root: AccessibilityNodeInfo?) { - if (root == null) - return + if (root == null) return root.refresh() val childCount = root.childCount for (i in 0 until childCount) { diff --git a/app/src/main/java/org/autojs/autojs/core/accessibility/NodeInfo.kt b/app/src/main/java/org/autojs/autojs/core/accessibility/NodeInfo.kt index 3aea3cb7..8f1b70bf 100644 --- a/app/src/main/java/org/autojs/autojs/core/accessibility/NodeInfo.kt +++ b/app/src/main/java/org/autojs/autojs/core/accessibility/NodeInfo.kt @@ -1,5 +1,6 @@ package org.autojs.autojs.core.accessibility +import android.annotation.SuppressLint import android.content.Context import android.content.pm.PackageManager import android.content.res.Resources @@ -17,7 +18,7 @@ import java.util.HashMap * Modified by SuperMonster003 as of Jun 17, 2022. */ -@Suppress("unused") +@Suppress("unused", "MemberVisibilityCanBePrivate") @Keep class NodeInfo(private val resources: Resources?, private val node: UiObject, var parent: NodeInfo?) { @@ -27,8 +28,8 @@ class NodeInfo(private val resources: Resources?, private val node: UiObject, va val bounds = boundsToString(boundsInScreen) val children = ArrayList() - var fullId: String? = node.viewIdResourceName - val simpleId = node.simpleId() + val fullId = node.fullId() + val id = node.simpleId() val desc = node.desc() val text = node.text() val className = node.className() @@ -59,6 +60,7 @@ class NodeInfo(private val resources: Resources?, private val node: UiObject, va val childCount = node.childCount() val actionNames = node.actionNames() + @SuppressLint("DiscouragedApi") val idHex = takeIf { resources != null && packageName != null && fullId != null }?.let { "0x${Integer.toHexString(resources!!.getIdentifier(fullId, null, null))}" } @@ -68,7 +70,7 @@ class NodeInfo(private val resources: Resources?, private val node: UiObject, va "childCount=${children.size}, " + "boundsInScreen=$boundsInScreen, " + "boundsInParent=$boundsInParent, " + - "id='$simpleId', " + + "id='$id', " + "desc='$desc', " + "packageName='$packageName', " + "text='$text', " + diff --git a/app/src/main/java/org/autojs/autojs/core/accessibility/SimpleActionAutomator.kt b/app/src/main/java/org/autojs/autojs/core/accessibility/SimpleActionAutomator.kt index 00821d10..006fed56 100644 --- a/app/src/main/java/org/autojs/autojs/core/accessibility/SimpleActionAutomator.kt +++ b/app/src/main/java/org/autojs/autojs/core/accessibility/SimpleActionAutomator.kt @@ -2,7 +2,6 @@ package org.autojs.autojs.core.accessibility -import android.accessibilityservice.AccessibilityService import android.accessibilityservice.GestureDescription import android.graphics.Bitmap import android.graphics.Rect @@ -15,7 +14,7 @@ import android.view.accessibility.AccessibilityNodeInfo import androidx.annotation.RequiresApi import androidx.core.view.accessibility.AccessibilityNodeInfoCompat import org.autojs.autojs.annotation.ScriptInterface -import org.autojs.autojs.core.accessibility.AccessibilityService.Companion.isRunning +import org.autojs.autojs.core.automator.AccessibilityEventWrapper import org.autojs.autojs.core.automator.GlobalActionAutomator import org.autojs.autojs.core.automator.UiObject import org.autojs.autojs.core.automator.action.ActionFactory @@ -27,7 +26,8 @@ import org.autojs.autojs.runtime.accessibility.AccessibilityConfig import org.autojs.autojs.runtime.api.ScreenMetrics import org.autojs.autojs.runtime.api.ScriptPromiseAdapter import org.autojs.autojs.util.DeveloperUtils - +import java.util.concurrent.atomic.AtomicInteger +import android.accessibilityservice.AccessibilityService as AndroidAccessibilityService /** * Created by Stardust on 2017/4/2. @@ -177,11 +177,23 @@ class SimpleActionAutomator(private val accessibilityBridge: AccessibilityBridge fun paste(target: ActionTarget) = performAction(target.createAction(AccessibilityNodeInfo.ACTION_PASTE)) @ScriptInterface - fun isServiceRunning() = isRunning() + fun isServiceRunning() = AccessibilityService.isRunning() @ScriptInterface fun ensureService() = accessibilityBridge.ensureServiceEnabled() + //todo:优化实现方式 + // TODO by SuperMonster003 on Jul 12, 2023. + // ! Ref to Auto.js Pro + fun registerEvent(eventName: String, callback: AccessibilityEventCallback) { + ensureService() + AccessibilityService.instance?.addAccessibilityEventCallback(eventName, callback) + } + + fun removeEvent(eventName: String) { + AccessibilityService.instance?.removeAccessibilityEventCallback(eventName) + } + private fun performAction(simpleAction: SimpleAction): Boolean { ensureService() if (AccessibilityConfig.isUnintendedGuardEnabled() && isRunningPackageSelf) { @@ -204,8 +216,8 @@ class SimpleActionAutomator(private val accessibilityBridge: AccessibilityBridge val promiseAdapter = mPromiseAdapter ?: ScriptPromiseAdapter().also { mPromiseAdapter = it } val service = accessibilityBridge.service!! val executor = service.mainExecutor - val callback = object : AccessibilityService.TakeScreenshotCallback { - override fun onSuccess(screenshot: AccessibilityService.ScreenshotResult) { + val callback = object : AndroidAccessibilityService.TakeScreenshotCallback { + override fun onSuccess(screenshot: AndroidAccessibilityService.ScreenshotResult) { val hardwareBuffer = Bitmap.wrapHardwareBuffer(screenshot.hardwareBuffer, screenshot.colorSpace) // @Hint by SuperMonster003 on Jun 9, 2023. @@ -222,7 +234,7 @@ class SimpleActionAutomator(private val accessibilityBridge: AccessibilityBridge } override fun onFailure(errorCode: Int) { - if (errorCode == AccessibilityService.ERROR_TAKE_SCREENSHOT_INTERVAL_TIME_SHORT) { + if (errorCode == AndroidAccessibilityService.ERROR_TAKE_SCREENSHOT_INTERVAL_TIME_SHORT) { Handler(Looper.getMainLooper()).postDelayed({ captureScreen() }, 50) @@ -239,9 +251,12 @@ class SimpleActionAutomator(private val accessibilityBridge: AccessibilityBridge } companion object { - + val accessibilityDelegateCounter = AtomicInteger(1000) val TAG: String = SimpleActionAutomator::class.java.name + interface AccessibilityEventCallback { + fun onAccessibilityEvent(event: AccessibilityEventWrapper) + } } } diff --git a/app/src/main/java/org/autojs/autojs/core/automator/AccessibilityEventWrapper.kt b/app/src/main/java/org/autojs/autojs/core/automator/AccessibilityEventWrapper.kt new file mode 100644 index 00000000..5e1bea68 --- /dev/null +++ b/app/src/main/java/org/autojs/autojs/core/automator/AccessibilityEventWrapper.kt @@ -0,0 +1,38 @@ +package org.autojs.autojs.core.automator + +import android.view.accessibility.AccessibilityEvent +import android.view.accessibility.AccessibilityNodeInfo + +/** + * Created by 抠脚本人 on Jul 10, 2023. + */ +class AccessibilityEventWrapper(event: AccessibilityEvent) { + val raw = event + val packageName: CharSequence? = event.packageName + val eventType = event.eventType + val eventTime = event.eventTime + val action = event.action + val isFullScreen = event.isFullScreen + val className = event.className + val source = event.source?.let { UiObject(it, getDepth(it), getIndexInParent(it)) } + + private fun getDepth(node: AccessibilityNodeInfo): Int { + var depth = 0 + var father = node.parent + while (father != null) { + depth++ + father = father.parent + } + return depth + } + + private fun getIndexInParent(node: AccessibilityNodeInfo): Int { + var index = 0 + val parent = node.parent ?: return 0 + while (parent.getChild(index) != node) { + index++ + } + return index + } +} + diff --git a/app/src/main/java/org/autojs/autojs/core/automator/UiObject.kt b/app/src/main/java/org/autojs/autojs/core/automator/UiObject.kt index 5d3eea36..bcaf88f7 100644 --- a/app/src/main/java/org/autojs/autojs/core/automator/UiObject.kt +++ b/app/src/main/java/org/autojs/autojs/core/automator/UiObject.kt @@ -31,11 +31,21 @@ import org.opencv.core.Size */ @Suppress("unused", "DEPRECATION") -open class UiObject constructor(info: Any?, private val allocator: AccessibilityNodeInfoAllocator?, private val depth: Int, private val indexInParent: Int) : AccessibilityNodeInfoCompat(info), UiObjectActions { +open class UiObject( + info: Any?, + private val allocator: AccessibilityNodeInfoAllocator?, + private val depth: Int, + private val indexInParent: Int +) : AccessibilityNodeInfoCompat(info), UiObjectActions { private val bounds by lazy { AccessibilityNodeInfoHelper.getBoundsInScreen(this) } - constructor(info: Any?, allocator: AccessibilityNodeInfoAllocator, indexInParent: Int) : this(info, allocator, 0, indexInParent) + constructor(info: Any?, allocator: AccessibilityNodeInfoAllocator, indexInParent: Int) : this( + info, + allocator, + 0, + indexInParent + ) @JvmOverloads constructor(info: Any?, depth: Int = 0, indexInParent: Int = -1) : this(info, null, depth, indexInParent) @@ -50,16 +60,35 @@ open class UiObject constructor(info: Any?, private val allocator: Accessibility } } catch (e: IllegalStateException) { // FIXME: 2017/5/5 - null + null.also { e.printStackTrace() } } open fun child(i: Int): UiObject? = try { super.getChild(i)?.run { UiObject(unwrap(), depth + 1, i) } } catch (e: IllegalStateException) { // FIXME: 2017/5/5 - null + null.also { e.printStackTrace() } } + @Deprecated("Deprecated in Java", ReplaceWith("offset(i)")) + open fun brother(i: Int): UiObject? = offset(i) + + open fun offset(i: Int): UiObject? = try { + parent()?.child(indexInParent + i) + } catch (e: ArrayIndexOutOfBoundsException) { + null.also { e.printStackTrace() } + } + + open fun sibling(i: Int): UiObject? = try { + parent()?.child(i) + } catch (e: ArrayIndexOutOfBoundsException) { + null.also { e.printStackTrace() } + } + + open fun nextSibling() = sibling(1) + + open fun previousSibling() = sibling(-1) + open fun childCount() = childCount fun hasChildren() = childCount > 0 @@ -332,28 +361,29 @@ open class UiObject constructor(info: Any?, private val allocator: Accessibility } } catch (e: IllegalStateException) { // FIXME: 2017/5/5 - false + false.also { e.printStackTrace() } } override fun performAction(action: Int): Boolean = try { super.performAction(action) } catch (e: IllegalStateException) { // FIXME: 2017/5/5 - false + false.also { e.printStackTrace() } } - override fun getChild(index: Int): AccessibilityNodeInfoCompat = allocator?.getChild(this, index) ?: super.getChild(index) + override fun getChild(index: Int): AccessibilityNodeInfoCompat = + allocator?.getChild(this, index) ?: super.getChild(index) override fun getParent(): AccessibilityNodeInfoCompat = allocator?.getParent(this) ?: super.getParent() override fun findAccessibilityNodeInfosByText(text: String): List { return allocator?.findAccessibilityNodeInfosByText(this, text) - ?: super.findAccessibilityNodeInfosByText(text) + ?: super.findAccessibilityNodeInfosByText(text) } override fun findAccessibilityNodeInfosByViewId(viewId: String): List { return allocator?.findAccessibilityNodeInfosByViewId(this, viewId) - ?: super.findAccessibilityNodeInfosByViewId(viewId) + ?: super.findAccessibilityNodeInfosByViewId(viewId) } override fun recycle() { @@ -375,7 +405,14 @@ open class UiObject constructor(info: Any?, private val allocator: Accessibility private val cArray = Array::class.java 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")) } @@ -386,7 +423,8 @@ open class UiObject constructor(info: Any?, private val allocator: Accessibility @JvmStatic fun isCompass(s: Any?): Boolean { - return (s as? CharSequence)?.run { this == COMPASS_PASS_ON || isEmpty() || contains("^(([pkc>]|s[<>]?)-?\\d*)+$".toRegex()) } ?: false + return (s as? CharSequence)?.run { this == COMPASS_PASS_ON || isEmpty() || contains("^(([pkc>]|s[<>]?)-?\\d*)+$".toRegex()) } + ?: false } @JvmStatic @@ -417,13 +455,18 @@ open class UiObject constructor(info: Any?, private val allocator: Accessibility @JvmStatic fun createRoot(root: AccessibilityNodeInfo?) = UiObject(root, null, 0, -1) - internal fun createRoot(root: AccessibilityNodeInfo?, allocator: AccessibilityNodeInfoAllocator?) = UiObject(root, allocator, 0, -1) + internal fun createRoot(root: AccessibilityNodeInfo?, allocator: AccessibilityNodeInfoAllocator?) = + UiObject(root, allocator, 0, -1) private fun arrayAliases(symbol: String, vararg others: String): Array { - return arrayOf("$symbol$symbol", "$symbol[]", "[$symbol]").plus(others.map { listOf("$it[]", "[$it]") }.flatten()) + return arrayOf("$symbol$symbol", "$symbol[]", "[$symbol]").plus(others.map { listOf("$it[]", "[$it]") } + .flatten()) } - private fun listAliases(@Suppress("SameParameterValue") symbol: String, vararg others: String): Array { + private fun listAliases( + @Suppress("SameParameterValue") symbol: String, + @Suppress("SameParameterValue") vararg others: String + ): Array { return arrayOf("$symbol{}", "{$symbol}").plus(others.map { listOf("$it{}", "{$it}") }.flatten()) } @@ -478,7 +521,12 @@ open class UiObject constructor(info: Any?, private val allocator: Accessibility } } - internal class Detector(private val compass: CharSequence? = COMPASS_PASS_ON, private val result: Result, val callback: BaseFunction? = null, private val selector: UiSelector? = UiSelector()) { + internal class Detector( + private val compass: CharSequence? = COMPASS_PASS_ON, + private val result: Result, + val callback: BaseFunction? = null, + private val selector: UiSelector? = UiSelector() + ) { fun detect(): Any? = when (val type = result.type.let { if (it is List<*>) it[0] else it }.toString()) { in RESULT_GROUP_WIDGET -> getUiObject() @@ -524,13 +572,17 @@ open class UiObject constructor(info: Any?, private val allocator: Accessibility private fun getUiObject() = result.byOne()?.compass(compass) - private fun getUiObjectCollection(transformer: (UiObject?) -> UiObject?) = UiObjectCollection.transform(result.byAll(), transformer).let { RhinoUtils.wrap(it) } + private fun getUiObjectCollection(transformer: (UiObject?) -> UiObject?) = + UiObjectCollection.transform(result.byAll(), transformer).let { RhinoUtils.wrap(it) } - private fun getUiObjectArray(transformer: (UiObject?) -> Any?) = UiObjectCollection.mapNotNull(result.byAll(), transformer).let { RhinoUtils.toArray(it) } + private fun getUiObjectArray(transformer: (UiObject?) -> Any?) = + UiObjectCollection.mapNotNull(result.byAll(), transformer).let { RhinoUtils.toArray(it) } - private fun detectWithCallback(callback: BaseFunction?, args: Array<*>): Any? = callback?.let { RhinoUtils.callFunction(it, args) } + private fun detectWithCallback(callback: BaseFunction?, args: Array<*>): Any? = + callback?.let { RhinoUtils.callFunction(it, args) } - private fun detectWithCallback(callback: BaseFunction?, arg: Any?): Any? = callback?.let { detectWithCallback(it, arrayOf(arg)) } + private fun detectWithCallback(callback: BaseFunction?, arg: Any?): Any? = + callback?.let { detectWithCallback(it, arrayOf(arg)) } } @@ -596,15 +648,45 @@ open class UiObject constructor(info: Any?, private val allocator: Accessibility "setLiveRegion", "setMaxTextLength", "setMovementGranularities", ), arrayOf(cString) to arrayOf( - "compass", "findAccessibilityNodeInfosByText", "findAccessibilityNodeInfosByViewId", "setClassName", "setContentDescription", - "setError", "setHintText", "setPackageName", "setPaneTitle", "setRoleDescription", "setStateDescription", "setText", - "setTooltipText", "setViewIdResourceName", + "compass", + "findAccessibilityNodeInfosByText", + "findAccessibilityNodeInfosByViewId", + "setClassName", + "setContentDescription", + "setError", + "setHintText", + "setPackageName", + "setPaneTitle", + "setRoleDescription", + "setStateDescription", + "setText", + "setTooltipText", + "setViewIdResourceName", ), arrayOf(cBoolean) to arrayOf( - "setAccessibilityFocused", "setCanOpenPopup", "setCheckable", "setChecked", "setClickable", "setEditable", "setEnabled", - "setFocusable", "setFocused", "setHeading", "setImportantForAccessibility", "setLongClickable", "setMultiLine", "setPassword", - "setScreenReaderFocusable", "setScrollable", "setSelected", "setShowingHintText", "setTextEntryKey", "setVisibleToUser", - "setContentInvalid", "setContextClickable", "setDismissable", + "setAccessibilityFocused", + "setCanOpenPopup", + "setCheckable", + "setChecked", + "setClickable", + "setEditable", + "setEnabled", + "setFocusable", + "setFocused", + "setHeading", + "setImportantForAccessibility", + "setLongClickable", + "setMultiLine", + "setPassword", + "setScreenReaderFocusable", + "setScrollable", + "setSelected", + "setShowingHintText", + "setTextEntryKey", + "setVisibleToUser", + "setContentInvalid", + "setContextClickable", + "setDismissable", ), arrayOf(cFloatPrim) to arrayOf("setProgress"), arrayOf(cIntPrim, cIntPrim) to arrayOf("setTextSelection", "setSelection", "scrollTo"), @@ -629,7 +711,11 @@ open class UiObject constructor(info: Any?, private val allocator: Accessibility constructor(resultType: String, resultParams: Array?) : super( when (resultParams) { null -> str(R.string.error_unknown_picker_result_type, resultType) - else -> str(R.string.error_unknown_picker_result_type_with_params, resultType, "[${resultParams.joinToString { it.toString() }}]") + else -> str( + R.string.error_unknown_picker_result_type_with_params, + resultType, + "[${resultParams.joinToString { it.toString() }}]" + ) } ) diff --git a/app/src/main/java/org/autojs/autojs/core/ui/JsViewHelper.java b/app/src/main/java/org/autojs/autojs/core/ui/JsViewHelper.java deleted file mode 100644 index ed62d1cd..00000000 --- a/app/src/main/java/org/autojs/autojs/core/ui/JsViewHelper.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.autojs.autojs.core.ui; - -import android.view.View; -import android.view.ViewGroup; - -import androidx.annotation.Nullable; - -import org.autojs.autojs.core.ui.inflater.util.Ids; - -/** - * Created by Stardust on 2017/5/14. - */ -public class JsViewHelper { - - @Nullable - public static View findViewByStringId(View view, String id) { - View result = view.findViewById(Ids.parse(id)); - if (result != null) - return result; - if (!(view instanceof ViewGroup group)) { - return null; - } - for (int i = 0; i < group.getChildCount(); i++) { - result = findViewByStringId(group.getChildAt(i), id); - if (result != null) - return result; - } - return null; - } - -} diff --git a/app/src/main/java/org/autojs/autojs/core/ui/JsViewHelper.kt b/app/src/main/java/org/autojs/autojs/core/ui/JsViewHelper.kt new file mode 100644 index 00000000..4d22c2f1 --- /dev/null +++ b/app/src/main/java/org/autojs/autojs/core/ui/JsViewHelper.kt @@ -0,0 +1,22 @@ +package org.autojs.autojs.core.ui + +import android.view.View +import android.view.ViewGroup +import org.autojs.autojs.core.ui.inflater.util.Ids + +/** + * Created by Stardust on 2017/5/14. + * Transformed by 抠脚本人 on Jul 10, 2023. + */ +object JsViewHelper { + @JvmStatic + fun findViewByStringId(view: View, id: String?): View? { + view.findViewById(Ids.parse(id))?.let { return it } + if (view is ViewGroup) { + for (i in 0 until view.childCount) { + findViewByStringId(view.getChildAt(i), id)?.let { return it } + } + } + return null + } +} diff --git a/app/src/main/java/org/autojs/autojs/model/autocomplete/CodeCompletion.java b/app/src/main/java/org/autojs/autojs/model/autocomplete/CodeCompletion.java deleted file mode 100644 index 7cc2b73c..00000000 --- a/app/src/main/java/org/autojs/autojs/model/autocomplete/CodeCompletion.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.autojs.autojs.model.autocomplete; - -/** - * Created by Stardust on 2018/2/3. - */ -public class CodeCompletion { - - private final String mHint; - private final String mUrl; - private final String mInsertText; - private final int mInsertPos; - - public CodeCompletion(String hint, String url, int insertPos) { - mHint = hint; - mUrl = url; - mInsertPos = insertPos; - mInsertText = null; - } - - public CodeCompletion(String hint, String url, String insertText) { - mHint = hint; - mUrl = url; - mInsertText = insertText; - mInsertPos = -1; - } - - public String getHint() { - return mHint; - } - - public String getUrl() { - return mUrl; - } - - public String getInsertText() { - if (mInsertText != null) - return mInsertText; - if (mInsertPos == 0) { - return mHint; - } - return mHint.substring(mInsertPos); - } -} diff --git a/app/src/main/java/org/autojs/autojs/model/autocomplete/CodeCompletion.kt b/app/src/main/java/org/autojs/autojs/model/autocomplete/CodeCompletion.kt new file mode 100644 index 00000000..2a2a00ce --- /dev/null +++ b/app/src/main/java/org/autojs/autojs/model/autocomplete/CodeCompletion.kt @@ -0,0 +1,34 @@ +package org.autojs.autojs.model.autocomplete + +/** + * Created by Stardust on 2018/2/3. + * Transformed by 抠脚本人 on Jul 11, 2023. + */ +class CodeCompletion { + val hint: String + val url: String? + private val mInsertText: String? + private val mInsertPos: Int + + constructor(hint: String, url: String?, insertPos: Int) { + this.hint = hint + this.url = url + mInsertPos = insertPos + mInsertText = null + } + + constructor(hint: String, url: String, insertText: String?) { + this.hint = hint + this.url = url + mInsertText = insertText + mInsertPos = -1 + } + + val insertText: String + get() { + if (mInsertText != null) return mInsertText + return if (mInsertPos == 0) { + hint + } else hint.substring(mInsertPos) + } +} \ No newline at end of file diff --git a/app/src/main/java/org/autojs/autojs/model/autocomplete/CodeCompletions.java b/app/src/main/java/org/autojs/autojs/model/autocomplete/CodeCompletions.java deleted file mode 100644 index 5a3b296d..00000000 --- a/app/src/main/java/org/autojs/autojs/model/autocomplete/CodeCompletions.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.autojs.autojs.model.autocomplete; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Stardust on 2017/9/27. - */ -public class CodeCompletions { - - - private final int mFrom; - private final List mCompletions; - - public CodeCompletions(int cursor, List completions) { - mFrom = cursor; - mCompletions = completions; - } - - public static CodeCompletions just(List hints) { - List completions = new ArrayList<>(hints.size()); - for (String hint : hints) { - completions.add(new CodeCompletion(hint, null, 0)); - } - return new CodeCompletions(-1, completions); - } - - public int getFrom() { - return mFrom; - } - - - public int size() { - return mCompletions.size(); - } - - public String getHint(int position) { - return mCompletions.get(position).getHint(); - } - - public CodeCompletion get(int pos) { - return mCompletions.get(pos); - } - - public String getUrl(int pos) { - return mCompletions.get(pos).getUrl(); - } -} diff --git a/app/src/main/java/org/autojs/autojs/model/autocomplete/CodeCompletions.kt b/app/src/main/java/org/autojs/autojs/model/autocomplete/CodeCompletions.kt new file mode 100644 index 00000000..60b82405 --- /dev/null +++ b/app/src/main/java/org/autojs/autojs/model/autocomplete/CodeCompletions.kt @@ -0,0 +1,34 @@ +package org.autojs.autojs.model.autocomplete + +/** + * Created by Stardust on 2017/9/27. + * Transformed by 抠脚本人 on Jul 11, 2023. + */ +class CodeCompletions(val from: Int, private val mCompletions: List) { + fun size(): Int { + return mCompletions.size + } + + fun getHint(position: Int): String { + return mCompletions[position].hint + } + + operator fun get(pos: Int): CodeCompletion { + return mCompletions[pos] + } + + fun getUrl(pos: Int): String? { + return mCompletions[pos].url + } + + companion object { + @JvmStatic + fun just(hints: List): CodeCompletions { + val completions: MutableList = ArrayList(hints.size) + for (hint in hints) { + completions.add(CodeCompletion(hint!!, null, 0)) + } + return CodeCompletions(-1, completions) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/org/autojs/autojs/model/autocomplete/Symbols.java b/app/src/main/java/org/autojs/autojs/model/autocomplete/Symbols.java index 270022c7..5b82d607 100644 --- a/app/src/main/java/org/autojs/autojs/model/autocomplete/Symbols.java +++ b/app/src/main/java/org/autojs/autojs/model/autocomplete/Symbols.java @@ -9,10 +9,10 @@ import java.util.Arrays; public class Symbols { private static final CodeCompletions sSymbols = CodeCompletions.just(Arrays.asList( - ",", ".", "=", ";", "\"", "'", "-", "_", + ",", ".", "=", ";", "\"", "'", "/", "-", "_", "(", ")", "[", "]", "{", "}", "<", ">", - "+", "*", "?", "$", "#", "@", "`", - "/", "\\", "&", "|", "!", "%", "×", "÷", + "+", "*", "?", ":", "$", "#", "@", "`", + "\\", "&", "|", "!", "%", "×", "÷", "∈", "∩", "∪", "∉", "⊙", "∅", "¥", "€", "°", "℃", "∵", "∴", "±", "≠", "≈", "α", "β", "γ", "λ", "μ", "π", "σ", "ω", diff --git a/app/src/main/java/org/autojs/autojs/runtime/ScriptRuntime.java b/app/src/main/java/org/autojs/autojs/runtime/ScriptRuntime.java index 772a6dbd..745f74c9 100644 --- a/app/src/main/java/org/autojs/autojs/runtime/ScriptRuntime.java +++ b/app/src/main/java/org/autojs/autojs/runtime/ScriptRuntime.java @@ -11,6 +11,7 @@ import org.autojs.autojs.AutoJs; import org.autojs.autojs.annotation.ScriptVariable; import org.autojs.autojs.concurrent.VolatileDispose; import org.autojs.autojs.core.accessibility.AccessibilityBridge; +import org.autojs.autojs.core.accessibility.AccessibilityService; import org.autojs.autojs.core.accessibility.SimpleActionAutomator; import org.autojs.autojs.core.accessibility.UiSelector; import org.autojs.autojs.core.activity.ActivityInfoProvider; @@ -528,6 +529,9 @@ public class ScriptRuntime { } }); + // 清空无障碍事件 + ignoresException(AccessibilityService::clearAccessibilityEventCallback); + ignoresException(RootUtils::resetRuntimeOverriddenRootModeState); ignoresException(ImageWrapper::recycleAll); diff --git a/app/src/main/java/org/autojs/autojs/ui/edit/EditorView.kt b/app/src/main/java/org/autojs/autojs/ui/edit/EditorView.kt index 4af57dc9..20493262 100644 --- a/app/src/main/java/org/autojs/autojs/ui/edit/EditorView.kt +++ b/app/src/main/java/org/autojs/autojs/ui/edit/EditorView.kt @@ -285,7 +285,16 @@ open class EditorView : FrameLayout, OnHintClickListener, ClickCallback, Toolbar .setFunctionsView(mFunctionsKeyboard) .setEditView(editor!!.codeEditText) .build() + //todo:不清楚作用,暂时注释掉 + // @Hint by SuperMonster003 on Jul 12, 2023. + // ! 此处的点击事件回调注册是为了使功能键盘智能提示的属性可以实现其接口对应的功能: + // ! 点击: 自动补全, 并根据情况添加括号或句点符号等. + // ! 长按: 以浮动窗口形式展示 [方法/属性/模块] 对应的文档内容 (如果存在的话). mFunctionsKeyboard!!.setClickCallback(this) + mShowFunctionsButton!!.setOnLongClickListener { + editor!!.beautifyCode() + true + } } private fun setUpInputMethodEnhancedBar() { @@ -321,7 +330,7 @@ open class EditorView : FrameLayout, OnHintClickListener, ClickCallback, Toolbar mAutoCompletion!!.onCursorChange(line, cursor) } - fun setTheme(theme: Theme?) { + private fun setTheme(theme: Theme?) { theme?.let { mEditorTheme = it editor!!.setTheme(it) @@ -575,11 +584,19 @@ open class EditorView : FrameLayout, OnHintClickListener, ClickCallback, Toolbar override fun onHintClick(completions: CodeCompletions, pos: Int) { val completion = completions[pos] - editor!!.insert(completion.insertText) + //todo:增加行注释 + if (completion.insertText=="/") { + editor!!.commentLine() + } else editor!!.insert(completion.insertText) } override fun onHintLongClick(completions: CodeCompletions, pos: Int) { val completion = completions[pos] + //todo:增加块注释 + if (completion.insertText=="/") { + editor!!.commentBlock() + return + } if (completion.url == null) return showManual(completion.url, completion.hint) } diff --git a/app/src/main/java/org/autojs/autojs/ui/edit/editor/CodeEditor.java b/app/src/main/java/org/autojs/autojs/ui/edit/editor/CodeEditor.java index fa1f692f..66978284 100644 --- a/app/src/main/java/org/autojs/autojs/ui/edit/editor/CodeEditor.java +++ b/app/src/main/java/org/autojs/autojs/ui/edit/editor/CodeEditor.java @@ -403,11 +403,14 @@ public class CodeEditor extends HVScrollView { public void beautifyCode() { setProgress(true); + int pos = mCodeEditText.getSelectionStart(); mJsBeautifier.beautify(mCodeEditText.getText().toString(), new JsBeautifier.Callback() { @Override public void onSuccess(String beautifiedCode) { setProgress(false); mCodeEditText.setText(beautifiedCode); + // 格式化后恢复光标位置 + mCodeEditText.setSelection(pos); } @Override @@ -418,6 +421,43 @@ public class CodeEditor extends HVScrollView { }); } + public void commentLine() { + //如果没有选中,则添加文本/,否则选中的行前加// + String selectionText = getSelectionRaw(); + if (selectionText.equals("")) { + insert("/"); + } else { + String[] lines = selectionText.split("\\n"); + StringBuilder commentedText = new StringBuilder(); + //处理取消注释 + if (lines[0].startsWith("//")) { + for (String line : lines) { + commentedText.append(line.substring(2)).append("\n"); + } + } else { + for (String line : lines) { + commentedText.append("//").append(line).append("\n"); + } + } + mReplacement = commentedText.toString().replaceAll("\\n$", ""); + replaceSelection(); + } + } + + public void commentBlock() { + String selectionText = getSelectionRaw(); + if (!selectionText.isEmpty()) { + String regex = "/\\*([^*]|\\*+[^*/])*\\*/"; + if (selectionText.matches(regex)) { + // 取消块注释 + mReplacement = selectionText.substring(2, selectionText.length() - 2); + } else { + // 增加块注释 + mReplacement = "/*" + selectionText + "*/"; + } + replaceSelection(); + } + } public void insert(String insertText) { int selection = Math.max(mCodeEditText.getSelectionStart(), 0); @@ -437,13 +477,17 @@ public class CodeEditor extends HVScrollView { return mCodeEditText.getText().toString(); } - public Observable getSelection() { + public String getSelectionRaw() { int s = mCodeEditText.getSelectionStart(); int e = mCodeEditText.getSelectionEnd(); if (s == e) { - return Observable.just(""); + return ""; } - return Observable.just(mCodeEditText.getText().toString().substring(s, e)); + return mCodeEditText.getText().toString().substring(s, e); + } + + public Observable getSelection() { + return Observable.just(getSelectionRaw()); } diff --git a/app/src/main/java/org/autojs/autojs/ui/floating/LayoutFloatyWindow.kt b/app/src/main/java/org/autojs/autojs/ui/floating/LayoutFloatyWindow.kt index 0f4af14c..7e23a25c 100644 --- a/app/src/main/java/org/autojs/autojs/ui/floating/LayoutFloatyWindow.kt +++ b/app/src/main/java/org/autojs/autojs/ui/floating/LayoutFloatyWindow.kt @@ -13,9 +13,11 @@ import org.autojs.autojs.ui.floating.layoutinspector.LayoutBoundsFloatyWindow import org.autojs.autojs.ui.floating.layoutinspector.LayoutHierarchyFloatyWindow import org.autojs.autojs.ui.floating.layoutinspector.NodeInfoView import org.autojs.autojs.ui.widget.BubblePopupMenu +import org.autojs.autojs.util.ClipboardUtils +import org.autojs.autojs.util.ViewUtils import org.autojs.autojs6.R -abstract class LayoutFloatyWindow(private val rootNode: NodeInfo?, private val context: Context, private val isServiceRelied: Boolean) : FullScreenFloatyWindow() { +abstract class LayoutFloatyWindow(private val rootNode: NodeInfo?, private val context: Context, private val isServiceRelied: Boolean) : FullScreenFloatyWindow(){ private lateinit var mServiceContext: Context private lateinit var mActions: LinkedHashMap @@ -27,6 +29,12 @@ abstract class LayoutFloatyWindow(private val rootNode: NodeInfo?, private val c private val mNodeInfoDialog by lazy { AppLevelThemeDialogBuilder(mServiceContext) .customView(mNodeInfoView, false) + .positiveText("生成") + .onPositive { _, _ -> + ViewUtils.showToast(context, "TODO") + val selector = mNodeInfoView.getCheckedDate().joinToString(".") + if (selector.isNotEmpty()) ClipboardUtils.setClip(context, selector) + } .build() .also { it.window!!.setType(FloatyWindowManger.getWindowType()) } } diff --git a/app/src/main/java/org/autojs/autojs/ui/floating/layoutinspector/LayoutBoundsView.kt b/app/src/main/java/org/autojs/autojs/ui/floating/layoutinspector/LayoutBoundsView.kt index 2bdce51d..fc048105 100644 --- a/app/src/main/java/org/autojs/autojs/ui/floating/layoutinspector/LayoutBoundsView.kt +++ b/app/src/main/java/org/autojs/autojs/ui/floating/layoutinspector/LayoutBoundsView.kt @@ -1,5 +1,6 @@ package org.autojs.autojs.ui.floating.layoutinspector +import android.annotation.SuppressLint import android.content.Context import android.graphics.Canvas import android.graphics.Color @@ -97,7 +98,7 @@ open class LayoutBoundsView : View { draw(canvas, child) } } - + @SuppressLint("ClickableViewAccessibility") override fun onTouchEvent(event: MotionEvent): Boolean { if (mRootNode != null) { setSelectedNode(findNodeAt(mRootNode!!, event.rawX.toInt(), event.rawY.toInt())) diff --git a/app/src/main/java/org/autojs/autojs/ui/floating/layoutinspector/LayoutHierarchyView.java b/app/src/main/java/org/autojs/autojs/ui/floating/layoutinspector/LayoutHierarchyView.java index 0666b0c8..8e6790ae 100644 --- a/app/src/main/java/org/autojs/autojs/ui/floating/layoutinspector/LayoutHierarchyView.java +++ b/app/src/main/java/org/autojs/autojs/ui/floating/layoutinspector/LayoutHierarchyView.java @@ -1,5 +1,6 @@ package org.autojs.autojs.ui.floating.layoutinspector; +import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; @@ -18,12 +19,7 @@ import org.autojs.autojs.ui.widget.LevelBeamView; import org.autojs.autojs.util.ViewUtils; import org.autojs.autojs6.R; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; -import java.util.Set; -import java.util.Stack; +import java.util.*; import pl.openrnd.multilevellistview.ItemInfo; import pl.openrnd.multilevellistview.MultiLevelListAdapter; @@ -40,7 +36,7 @@ public class LayoutHierarchyView extends MultiLevelListView { public interface OnItemLongClickListener { void onItemLongClick(View view, NodeInfo nodeInfo); } - + private final Map nodeMap = new LinkedHashMap<>(); private Adapter mAdapter; private OnItemLongClickListener mOnItemLongClickListener; private final AdapterView.OnItemLongClickListener mOnItemLongClickListenerProxy = new AdapterView.OnItemLongClickListener() { @@ -111,17 +107,41 @@ public class LayoutHierarchyView extends MultiLevelListView { } private void setClickedItem(View view, NodeInfo item) { - mClickedNodeInfo = item; if (mClickedView == null) { mOriginalBackground = view.getBackground(); } else { mClickedView.setBackground(mOriginalBackground); + drawListItem(mClickedNodeInfo, false); } view.setBackgroundColor(mClickedColor); + drawListItem(item, true); + mClickedNodeInfo = item; mClickedView = view; invalidate(); } + private void drawListItem(NodeInfo info, Boolean draw) { + ArrayList list = new ArrayList<>(); + NodeInfo currentInfo = info; + while (true) { + currentInfo = currentInfo.getParent(); + if (currentInfo == null) break; + ViewHolder vh = nodeMap.get(currentInfo); + list.add(vh); + } + //todo:选用能适应深色模式的字体颜色 + //fixme:列表滑动时listview数据错乱 + if (draw) { + for (ViewHolder vh : list) { + vh.nameView.setTextColor(Color.RED); // 设置字体颜色为红色 + } + } else { + for (ViewHolder vh : list) { + vh.nameView.setTextColor(Color.BLACK); // 设置字体颜色为红色 + } + } + } + private void initPaint() { mPaint = new Paint(); mPaint.setColor(Color.DKGRAY); @@ -186,7 +206,7 @@ public class LayoutHierarchyView extends MultiLevelListView { return found; } - private class ViewHolder { + private static class ViewHolder { TextView nameView; TextView infoView; ImageView arrowView; @@ -220,6 +240,7 @@ public class LayoutHierarchyView extends MultiLevelListView { return mInitiallyExpandedNodes.contains((NodeInfo) object); } + @SuppressLint("InflateParams") @Override public View getViewForObject(Object object, View convertView, ItemInfo itemInfo) { NodeInfo nodeInfo = (NodeInfo) object; @@ -231,8 +252,9 @@ public class LayoutHierarchyView extends MultiLevelListView { } else { viewHolder = (ViewHolder) convertView.getTag(); } - - viewHolder.nameView.setText(simplifyClassName(nodeInfo.getClassName())); + nodeMap.put(nodeInfo,viewHolder); + //对于id,desc,text,clickable,longClickable不为空的显示额外信息 + viewHolder.nameView.setText(extraInfo(nodeInfo)); viewHolder.nodeInfo = nodeInfo; if (viewHolder.infoView.getVisibility() == VISIBLE) viewHolder.infoView.setText(getItemInfoDsc(itemInfo)); @@ -266,6 +288,31 @@ public class LayoutHierarchyView extends MultiLevelListView { return s; } + private String extraInfo(NodeInfo nodeInfo) { + String extra = simplifyClassName(nodeInfo.getClassName()); + ArrayList info = new ArrayList<>(); + if (nodeInfo.getId() != null) { + info.add("id=" + nodeInfo.getId()); + } + if (!nodeInfo.getText().equals("")) { + info.add("text=" + nodeInfo.getText()); + } + if (nodeInfo.getDesc() != null) { + info.add("desc=" + nodeInfo.getDesc()); + } + if (nodeInfo.getClickable()) { + info.add("clickable"); + } + if (nodeInfo.getLongClickable()) { + info.add("longClickable"); + } + //字符串拼接 + String others = String.join(", ", info); + if (!others.isEmpty()) { + return extra + " [" + others + "]"; + } + return extra; + } private String getItemInfoDsc(ItemInfo itemInfo) { StringBuilder builder = new StringBuilder(); diff --git a/app/src/main/java/org/autojs/autojs/ui/floating/layoutinspector/NodeInfoView.kt b/app/src/main/java/org/autojs/autojs/ui/floating/layoutinspector/NodeInfoView.kt index 7b2988a8..a08702c0 100644 --- a/app/src/main/java/org/autojs/autojs/ui/floating/layoutinspector/NodeInfoView.kt +++ b/app/src/main/java/org/autojs/autojs/ui/floating/layoutinspector/NodeInfoView.kt @@ -1,10 +1,12 @@ package org.autojs.autojs.ui.floating.layoutinspector +import android.annotation.SuppressLint import android.content.Context import android.util.AttributeSet import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.CheckBox import android.widget.TextView import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView @@ -20,7 +22,7 @@ import java.lang.reflect.Field * Modified by SuperMonster003 as of Dec 1, 2021. */ class NodeInfoView : RecyclerView { - + //todo:调整数据结构,对话框关闭后根据已勾选的属性,生成选择器 private val data = Array(FIELDS.size + 1) { Array(2) { "" } } constructor(context: Context) : super(context) @@ -41,6 +43,7 @@ class NodeInfoView : RecyclerView { ) } + @SuppressLint("NotifyDataSetChanged") fun setNodeInfo(nodeInfo: NodeInfo) { for (i in FIELDS.indices) { try { @@ -71,6 +74,14 @@ class NodeInfoView : RecyclerView { } } + fun getCheckedDate(): Array { + //todo:数据增加checked属性,区分已选中项目 + val checkedArr = data.filter { it[0] == "id" || it[0] == "text" } + return Array(checkedArr.size) { + dataToFx(checkedArr[it]) + } + } + private inner class Adapter : RecyclerView.Adapter() { val mViewTypeHeader = 0 @@ -84,6 +95,7 @@ class NodeInfoView : RecyclerView { override fun onBindViewHolder(holder: ViewHolder, position: Int) { holder.apply { data[position].let { + //attrChecked.isChecked = false attrName.text = it[0] attrValue.text = it[1] } @@ -97,7 +109,7 @@ class NodeInfoView : RecyclerView { } internal inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { - + //val attrChecked: CheckBox = itemView.findViewById(R.id.generate) val attrName: TextView = itemView.findViewById(R.id.name) val attrValue: TextView = itemView.findViewById(R.id.value) @@ -130,7 +142,7 @@ class NodeInfoView : RecyclerView { private val FIELD_NAMES = arrayOf( // Common - "packageName", "simpleId", "fullId", "idHex", + "packageName", "id", "fullId", "idHex", "desc", "text", "bounds", "className", "clickable", "longClickable", "scrollable", diff --git a/app/src/main/java/org/autojs/autojs/ui/floating/layoutinspector/OnNodeInfoSelectListener.java b/app/src/main/java/org/autojs/autojs/ui/floating/layoutinspector/OnNodeInfoSelectListener.java deleted file mode 100644 index cfafc3c1..00000000 --- a/app/src/main/java/org/autojs/autojs/ui/floating/layoutinspector/OnNodeInfoSelectListener.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.autojs.autojs.ui.floating.layoutinspector; - -import org.autojs.autojs.core.accessibility.NodeInfo; - -/** - * Created by Stardust on 2017/3/10. - */ -public interface OnNodeInfoSelectListener { - - void onNodeSelect(NodeInfo info); - -} diff --git a/app/src/main/java/org/autojs/autojs/ui/floating/layoutinspector/OnNodeInfoSelectListener.kt b/app/src/main/java/org/autojs/autojs/ui/floating/layoutinspector/OnNodeInfoSelectListener.kt new file mode 100644 index 00000000..1f65773d --- /dev/null +++ b/app/src/main/java/org/autojs/autojs/ui/floating/layoutinspector/OnNodeInfoSelectListener.kt @@ -0,0 +1,10 @@ +package org.autojs.autojs.ui.floating.layoutinspector + +import org.autojs.autojs.core.accessibility.NodeInfo + +/** + * Created by Stardust on 2017/3/10. + */ +fun interface OnNodeInfoSelectListener { + fun onNodeSelect(info: NodeInfo) +} diff --git a/app/src/main/res/layout/editor_view.xml b/app/src/main/res/layout/editor_view.xml index 9b2d69e3..3a2c4eba 100644 --- a/app/src/main/res/layout/editor_view.xml +++ b/app/src/main/res/layout/editor_view.xml @@ -63,15 +63,16 @@ android:layout_alignParentBottom="true" /> + android:id="@+id/functions" + android:layout_width="40dp" + android:layout_height="35dp" + android:layout_alignParentStart="true" + android:layout_alignParentTop="true" + android:background="?selectableItemBackgroundBorderless" + android:contentDescription="@string/fun" + android:padding="6dp" + android:src="@drawable/ic_ali_fx" + app:tint="#222329" /> + Colon must follow a valid IP address Repeated dot symbol Repeated colon symbol + 函数 Total: %d item diff --git a/settings.gradle.kts b/settings.gradle.kts index 08b79593..2f65e6a0 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,3 +1,5 @@ +enableFeaturePreview("STABLE_CONFIGURATION_CACHE") + include( ":app", ":libs:android-job-simplified-1.4.3", diff --git a/version.properties b/version.properties index 617c4e6a..c30b3bbe 100644 --- a/version.properties +++ b/version.properties @@ -4,7 +4,7 @@ COMPILE_SDK_VERSION=33 JAVA_VERSION=20 MIN_SDK_VERSION=24 TARGET_SDK_VERSION=33 -#2006 +#2006/2020 VERSION_BUILD=1999 VERSION_NAME=6.3.3 VSCODE_EXT_REQUIRED_VERSION=1.0.8