From 770bd657e00bd7011662ac047853a4eaea7148c0 Mon Sep 17 00:00:00 2001 From: SuperMonster003 Date: Sun, 8 Mar 2026 15:38:35 +0800 Subject: [PATCH] =?UTF-8?q?6.7.0=20-=20Alpha23=20-=20=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E7=BC=96=E8=BE=91=E5=99=A8=E6=94=AF=E6=8C=81=20"-",=20"=3D",?= =?UTF-8?q?=20"(",=20"[",=20"{",=20"<"=20=E7=AD=89=E6=8C=89=E9=94=AE?= =?UTF-8?q?=E9=95=BF=E6=8C=89=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .changelog/lang_zh-Hans.json | 1 + .../org/autojs/autojs/ui/edit/EditorMenu.java | 2 +- .../org/autojs/autojs/ui/edit/EditorView.kt | 12 ++- .../ui/edit/completion/CodeCompletionBar.java | 29 ++++--- .../autojs/ui/edit/editor/CodeEditor.kt | 78 +++++++++++++++---- .../edit/editor/CodeEditorCommentHelper.java | 21 ----- .../java/org/autojs/autojs/util/ViewUtils.kt | 78 +++++++++++++++++++ version.properties | 6 +- 8 files changed, 172 insertions(+), 55 deletions(-) delete mode 100644 app/src/main/java/org/autojs/autojs/ui/edit/editor/CodeEditorCommentHelper.java diff --git a/.changelog/lang_zh-Hans.json b/.changelog/lang_zh-Hans.json index 0e19e4b4..5535f88e 100644 --- a/.changelog/lang_zh-Hans.json +++ b/.changelog/lang_zh-Hans.json @@ -153,6 +153,7 @@ "代码编辑器 \"查找/替换\" 支持状态持久化及实时显示搜索计数信息", "代码编辑器提示保存时确保保存成功后再退出编辑器以降低保存失败率", "代码编辑器保存按钮的状态更符合用户主观逻辑", + "代码编辑器支持 \"-\", \"=\", \"(\", \"[\", \"{\", \"<\" 等按键长按功能", "打包应用打包过程对话框增加 \"中止\" 按钮", "打包应用打包过程对话框的显示方式并增加耗时统计", "打包应用页面默认勾选必要权限 (WAKE_LOCK/INTERNET/WRITE_EXTERNAL_STORAGE) _[`issue #397`](http://issues.autojs6.com/397)_", diff --git a/app/src/main/java/org/autojs/autojs/ui/edit/EditorMenu.java b/app/src/main/java/org/autojs/autojs/ui/edit/EditorMenu.java index f8541f64..2321e69d 100644 --- a/app/src/main/java/org/autojs/autojs/ui/edit/EditorMenu.java +++ b/app/src/main/java/org/autojs/autojs/ui/edit/EditorMenu.java @@ -362,7 +362,7 @@ public class EditorMenu { return tryDoing(() -> mEditor.setText("")); } if (itemId == R.id.action_comment) { - return tryDoing(mEditor.commentHelper::handle); + return tryDoing(mEditor.commentHelper::toggle); } if (itemId == R.id.action_beautify) { return tryDoing(mEditorView::beautifyCode); 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 326eccc7..a52a5908 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 @@ -2566,7 +2566,17 @@ class EditorView : LinearLayout, OnHintClickListener, ClickCallback, ToolbarFrag completions[pos].let { when { // @Inspired by 抠脚本人 (https://github.com/little-alei) on Jul 13, 2023. - it.insertText == "/" -> editor.commentHelper.handle() + it.insertText == "/" -> editor.commentHelper.toggle() + it.insertText == "=" -> editor.clear() + it.insertText == "-" -> editor.deleteLine() + it.insertText == "(" -> editor.moveCursor(-1) + it.insertText == ")" -> editor.moveCursor(1) + it.insertText == "[" -> editor.jumpToLineStart() + it.insertText == "]" -> editor.jumpToLineEnd() + it.insertText == "{" -> editor.jumpToStart() + it.insertText == "}" -> editor.jumpToEnd() + it.insertText == "<" -> editor.jumpToPrevLine() + it.insertText == ">" -> editor.jumpToNextLine() it.url != null -> showManual(it.url, it.hint) } } diff --git a/app/src/main/java/org/autojs/autojs/ui/edit/completion/CodeCompletionBar.java b/app/src/main/java/org/autojs/autojs/ui/edit/completion/CodeCompletionBar.java index 9d8e9ee8..7b34552c 100644 --- a/app/src/main/java/org/autojs/autojs/ui/edit/completion/CodeCompletionBar.java +++ b/app/src/main/java/org/autojs/autojs/ui/edit/completion/CodeCompletionBar.java @@ -5,48 +5,42 @@ import android.os.Looper; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; +import android.view.ViewConfiguration; import android.view.ViewGroup; import android.widget.TextView; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.recyclerview.widget.RecyclerView; - -import org.autojs.autojs.model.autocomplete.CodeCompletions; import org.autojs.autojs.groundwork.WrapContentLinearLayoutManager; +import org.autojs.autojs.model.autocomplete.CodeCompletions; +import org.autojs.autojs.util.ViewUtils; import org.autojs.autojs6.R; /** * Created by Stardust on Feb 17, 2017. + * Modified by SuperMonster003 as of Mar 8, 2026. */ public class CodeCompletionBar extends RecyclerView { - public interface OnHintClickListener { - void onHintClick(CodeCompletions completions, int pos); - - void onHintLongClick(CodeCompletions completions, int pos); - } - private int mTextColor; private CodeCompletions mCodeCompletions; private OnHintClickListener mOnHintClickListener; private final OnClickListener mOnCodeCompletionItemClickListener = new OnClickListener() { @Override public void onClick(View v) { - int position = getChildViewHolder(v).getAdapterPosition(); + int position = getChildViewHolder(v).getBindingAdapterPosition(); if (position >= 0 && position < mCodeCompletions.size()) { if (mOnHintClickListener != null) { mOnHintClickListener.onHintClick(mCodeCompletions, position); } } - } }; private final OnLongClickListener mOnCodeCompletionItemLongClickListener = new OnLongClickListener() { @Override public boolean onLongClick(View v) { - int position = getChildViewHolder(v).getAdapterPosition(); + int position = getChildViewHolder(v).getBindingAdapterPosition(); if (position < 0 || position >= mCodeCompletions.size()) return false; if (mOnHintClickListener != null) { @@ -127,7 +121,18 @@ public class CodeCompletionBar extends RecyclerView { super(itemView); itemView.setOnClickListener(mOnCodeCompletionItemClickListener); itemView.setOnLongClickListener(mOnCodeCompletionItemLongClickListener); + itemView.setOnTouchListener( + new ViewUtils.DelayedLongPressTouchListener( + itemView.getContext(), + (long) (ViewConfiguration.getLongPressTimeout() * 1.25) + ) + ); } } + public interface OnHintClickListener { + void onHintClick(CodeCompletions completions, int pos); + + void onHintLongClick(CodeCompletions completions, int pos); + } } diff --git a/app/src/main/java/org/autojs/autojs/ui/edit/editor/CodeEditor.kt b/app/src/main/java/org/autojs/autojs/ui/edit/editor/CodeEditor.kt index 92648edd..81fbc6b0 100644 --- a/app/src/main/java/org/autojs/autojs/ui/edit/editor/CodeEditor.kt +++ b/app/src/main/java/org/autojs/autojs/ui/edit/editor/CodeEditor.kt @@ -6,6 +6,7 @@ import android.graphics.Canvas import android.os.Handler import android.os.Looper import android.os.SystemClock +import android.text.Layout import android.util.AttributeSet import android.view.LayoutInflater import android.view.MotionEvent @@ -316,14 +317,16 @@ class CodeEditor : HVScrollView { when (ev.actionMasked) { MotionEvent.ACTION_DOWN, MotionEvent.ACTION_POINTER_DOWN, - MotionEvent.ACTION_MOVE -> { + MotionEvent.ACTION_MOVE, + -> { // Mark touching as early as possible. // zh-CN: 尽可能早地标记触摸中状态. mUserTouching = true } MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL, - MotionEvent.ACTION_POINTER_UP -> { + MotionEvent.ACTION_POINTER_UP, + -> { // Clear touching flag when gesture ends. // zh-CN: 手势结束时清除触摸中标记. mUserTouching = false @@ -397,6 +400,10 @@ class CodeEditor : HVScrollView { } } + fun clear() { + codeEditText.setText("") + } + fun jumpToStart() { codeEditText.setSelection(0) } @@ -417,15 +424,46 @@ class CodeEditor : HVScrollView { val layout = codeEditText.layout val line = LayoutHelper.getLineOfChar(layout, minOf(codeEditText.selectionStart, codeEditText.selectionEnd)) if (line >= 0 && line < layout.lineCount) { - val lineEnd = layout.getLineEnd(line) - val text = codeEditText.text.toString() - val finalPosition = when { - lineEnd > 0 && text[lineEnd - 1] == '\n' -> { - lineEnd - 1 - } - else -> lineEnd - } - codeEditText.setSelection(finalPosition) + codeEditText.setSelection(getLineEndWithoutTrailingNewline(layout, line)) + } + } + + fun jumpToNextLine() { + val layout = codeEditText.layout + val cursor = minOf(codeEditText.selectionStart, codeEditText.selectionEnd) + val line = LayoutHelper.getLineOfChar(layout, cursor) + jumpToLinePreservingColumn(layout, line, line + 1, cursor) + } + + fun jumpToPrevLine() { + val layout = codeEditText.layout + val cursor = minOf(codeEditText.selectionStart, codeEditText.selectionEnd) + val line = LayoutHelper.getLineOfChar(layout, cursor) + jumpToLinePreservingColumn(layout, line, line - 1, cursor) + } + + private fun jumpToLinePreservingColumn(layout: Layout, fromLine: Int, targetLine: Int, cursor: Int) { + if (fromLine !in 0 until layout.lineCount || targetLine !in 0 until layout.lineCount) { + return + } + val fromLineStart = layout.getLineStart(fromLine) + val fromLineEnd = getLineEndWithoutTrailingNewline(layout, fromLine) + val fromLineCursor = cursor.coerceIn(fromLineStart, fromLineEnd) + val desiredColumn = fromLineCursor - fromLineStart + + val targetLineStart = layout.getLineStart(targetLine) + val targetLineEnd = getLineEndWithoutTrailingNewline(layout, targetLine) + val targetCursor = (targetLineStart + desiredColumn).coerceAtMost(targetLineEnd) + codeEditText.setSelection(targetCursor) + } + + private fun getLineEndWithoutTrailingNewline(layout: Layout, line: Int): Int { + val lineEnd = layout.getLineEnd(line) + val text = codeEditText.text ?: return lineEnd + return if (lineEnd > 0 && lineEnd <= text.length && text[lineEnd - 1] == '\n') { + lineEnd - 1 + } else { + lineEnd } } @@ -739,13 +777,19 @@ class CodeEditor : HVScrollView { fun onCursorChange(line: String, cursor: Int) } - inner class CommentHelper : CodeEditorCommentHelper { + inner class CommentHelper { private val prefix = "//" - override fun handle() = toggle() + fun toggle() { + if (isCommented()) { + uncomment() + } else { + comment() + } + } - override fun comment() { + fun comment() { var selectionEnd = codeEditText.selectionEnd val insetPosition = getProperWhitespaceAmount() var hasEverMatched = false @@ -776,7 +820,7 @@ class CodeEditor : HVScrollView { codeEditText.setSelection(selectionEnd) } - override fun uncomment() { + fun uncomment() { var selectionEnd = codeEditText.selectionEnd replaceSelectedLines(Regex("(\\s*)($prefix\\s?)(.*)")) { matchResult -> @@ -788,7 +832,7 @@ class CodeEditor : HVScrollView { codeEditText.setSelection(selectionEnd) } - override fun isCommented(): Boolean { + fun isCommented(): Boolean { var atLeastOneWithPrefix = false val allMatched = getCoveredLinesText().split("\n").all { it.matches(Regex("\\s*")) || it @@ -859,4 +903,4 @@ class CodeEditor : HVScrollView { // # } // # } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/autojs/autojs/ui/edit/editor/CodeEditorCommentHelper.java b/app/src/main/java/org/autojs/autojs/ui/edit/editor/CodeEditorCommentHelper.java deleted file mode 100644 index 1c81d6b5..00000000 --- a/app/src/main/java/org/autojs/autojs/ui/edit/editor/CodeEditorCommentHelper.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.autojs.autojs.ui.edit.editor; - -public interface CodeEditorCommentHelper { - - void handle(); - - void comment(); - - void uncomment(); - - boolean isCommented(); - - default void toggle() { - if (isCommented()) { - uncomment(); - } else { - comment(); - } - } - -} diff --git a/app/src/main/java/org/autojs/autojs/util/ViewUtils.kt b/app/src/main/java/org/autojs/autojs/util/ViewUtils.kt index c6c85384..8fa5cba3 100644 --- a/app/src/main/java/org/autojs/autojs/util/ViewUtils.kt +++ b/app/src/main/java/org/autojs/autojs/util/ViewUtils.kt @@ -76,6 +76,7 @@ import org.autojs.autojs.util.StringUtils.key import org.autojs.autojs6.R import kotlin.math.abs import kotlin.math.floor +import kotlin.math.max import kotlin.math.min import kotlin.math.roundToInt import android.text.TextUtils as AndroidTextUtils @@ -1689,6 +1690,83 @@ object ViewUtils { } } + class DelayedLongPressTouchListener(context: Context, longPressDelayMs: Long) : View.OnTouchListener { + + private val longPressDelayMs: Long + private val touchSlop: Int + + private var downX = 0f + private var downY = 0f + private var tracking = false + private var longPressed = false + private var pendingLongPress: Runnable? = null + + init { + this.longPressDelayMs = max(0, longPressDelayMs) + this.touchSlop = ViewConfiguration.get(context).getScaledTouchSlop() + } + + override fun onTouch(v: View, event: MotionEvent): Boolean = + when (event.getActionMasked()) { + MotionEvent.ACTION_DOWN -> { + downX = event.getX() + downY = event.getY() + tracking = true + longPressed = false + v.setPressed(true) + + cancelPending(v) + pendingLongPress = Runnable { + if (tracking && v.isPressed()) { + longPressed = v.performLongClick() + } + } + v.postDelayed(pendingLongPress, longPressDelayMs) + true + } + MotionEvent.ACTION_MOVE -> { + if (tracking) { + val dx = abs(event.getX() - downX) + val dy = abs(event.getY() - downY) + if (dx > touchSlop || dy > touchSlop) { + cancelGesture(v) + } + } + true + } + MotionEvent.ACTION_UP -> { + cancelPending(v) + v.setPressed(false) + + val shouldClick = tracking && !longPressed + tracking = false + if (shouldClick) { + v.performClick() + } + true + } + MotionEvent.ACTION_CANCEL -> { + cancelGesture(v) + true + } + else -> false + } + + private fun cancelPending(v: View) { + if (pendingLongPress != null) { + v.removeCallbacks(pendingLongPress) + pendingLongPress = null + } + } + + private fun cancelGesture(v: View) { + cancelPending(v) + v.setPressed(false) + tracking = false + longPressed = false + } + } + private class TextSizeScaleListener(private val textView: TextView) : ScaleGestureDetector.SimpleOnScaleGestureListener() { private val mMinTextSize = 4.0f diff --git a/version.properties b/version.properties index 47dfa942..316114dd 100644 --- a/version.properties +++ b/version.properties @@ -1,5 +1,5 @@ -#Sat Mar 07 23:49:47 CST 2026 -BUILD_TIME=1772898587711 +#Sun Mar 08 15:18:59 CST 2026 +BUILD_TIME=1772954339154 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=3781 +VERSION_BUILD=3782 VERSION_NAME=6.7.0 Alpha23 VSCODE_EXT_REQUIRED_VERSION=1.0.13