Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bb4998d239 | |||
| 25bd9a866e | |||
|
|
ed3eb10e88 | ||
|
|
49ea44ec72 | ||
|
|
9f145340ab | ||
|
|
3ce61cf084 | ||
|
|
f6cbb41f90 | ||
|
|
6474f912a4 |
@@ -698,7 +698,7 @@
|
||||
android:theme="@style/ScriptTheme.Transparent" />
|
||||
|
||||
<service
|
||||
android:name="org.autojs.autojs.core.accessibility.AccessibilityServiceUsher"
|
||||
android:name="com.google.android.accessibility.selecttospeak.SelectToSpeakService"
|
||||
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
|
||||
android:exported="true">
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.autojs.autojs.core.accessibility
|
||||
package com.google.android.accessibility.selecttospeak
|
||||
|
||||
import android.accessibilityservice.AccessibilityServiceInfo
|
||||
import android.os.Build
|
||||
@@ -6,7 +6,7 @@ import android.util.Log
|
||||
import org.autojs.autojs.core.pref.Pref
|
||||
import org.autojs.autojs.core.accessibility.AccessibilityService as CoreAccessibilityService
|
||||
|
||||
class AccessibilityServiceUsher : CoreAccessibilityService() {
|
||||
class SelectToSpeakService : CoreAccessibilityService() {
|
||||
|
||||
override fun onServiceConnected() {
|
||||
Log.d(TAG, "onServiceConnected")
|
||||
@@ -29,7 +29,7 @@ class AccessibilityServiceUsher : CoreAccessibilityService() {
|
||||
|
||||
companion object {
|
||||
|
||||
private val TAG = AccessibilityServiceUsher::class.java.simpleName
|
||||
private val TAG = SelectToSpeakService::class.java.simpleName
|
||||
|
||||
}
|
||||
|
||||
@@ -383,10 +383,17 @@ public class ConcatReader extends Reader {
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
if (closed) return;
|
||||
IOException first = null;
|
||||
for (Reader reader : readerQueue) {
|
||||
reader.close();
|
||||
try {
|
||||
reader.close();
|
||||
} catch (IOException e) {
|
||||
if (first == null) first = e;
|
||||
else first.addSuppressed(e);
|
||||
}
|
||||
}
|
||||
closed = true;
|
||||
if (first != null) throw first;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,6 +7,7 @@ import android.provider.Settings
|
||||
import android.provider.Settings.Secure
|
||||
import android.text.TextUtils
|
||||
import android.util.Log
|
||||
import com.google.android.accessibility.selecttospeak.SelectToSpeakService
|
||||
import org.autojs.autojs.annotation.ScriptInterface
|
||||
import org.autojs.autojs.app.GlobalAppContext
|
||||
import org.autojs.autojs.core.pref.Pref
|
||||
@@ -30,7 +31,7 @@ class AccessibilityTool(private val context: Context? = null) {
|
||||
private val mContext: Context
|
||||
get() = context ?: mApplicationContext
|
||||
private val mServiceNamePrefix = mApplicationContext.packageName
|
||||
private val mServiceNameSuffix = AccessibilityServiceUsher::class.java.name
|
||||
private val mServiceNameSuffix = SelectToSpeakService::class.java.name
|
||||
private val mServiceName = "$mServiceNamePrefix/$mServiceNameSuffix"
|
||||
|
||||
@ScriptInterface
|
||||
|
||||
@@ -4,6 +4,11 @@ import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Color;
|
||||
import android.text.SpannableString;
|
||||
import android.text.Spanned;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.text.style.ClickableSpan;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
@@ -17,6 +22,14 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.autojs.autojs.theme.ThemeColorHelper;
|
||||
import org.autojs.autojs.tool.MapBuilder;
|
||||
import org.autojs.autojs.ui.log.LogActivity;
|
||||
@@ -24,11 +37,6 @@ import org.autojs.autojs.util.DisplayUtils;
|
||||
import org.autojs.autojs.util.ViewUtils;
|
||||
import org.autojs.autojs6.R;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Created by Stardust on May 2, 2017.
|
||||
* <p>
|
||||
@@ -37,6 +45,21 @@ import java.util.Objects;
|
||||
public class ConsoleView extends FrameLayout implements ConsoleImpl.LogListener {
|
||||
|
||||
private final static int sRefreshInterval = 100;
|
||||
|
||||
// Stack frame link pattern: matches "file:line" or "file:line:col" format
|
||||
// Examples: "/sdcard/script.js:10", "script.js:10:5", "file:///path/to/script.js:42:3"
|
||||
private static final Pattern STACK_FRAME_PATTERN = Pattern.compile(
|
||||
"(?:file:)?((?:/[\\S]+?|[^\\s:]+?)\\.js):(\\d+)(?::(\\d+))?"
|
||||
);
|
||||
private static final int LINK_COLOR = 0xFF2196F3; // Blue color for clickable links
|
||||
|
||||
private boolean mEnableStackFrameLinks = false;
|
||||
private OnStackFrameClickListener mStackFrameClickListener;
|
||||
|
||||
public interface OnStackFrameClickListener {
|
||||
void onStackFrameClick(String fileName, int lineNumber, int columnNumber);
|
||||
}
|
||||
|
||||
private final Map<Integer, Integer> mColors = new MapBuilder<Integer, Integer>().build();
|
||||
private ConsoleImpl mConsole;
|
||||
private WeakReference<LogActivity> mLogActivity = null;
|
||||
@@ -228,6 +251,66 @@ public class ConsoleView extends FrameLayout implements ConsoleImpl.LogListener
|
||||
mIsPinchToZoomEnabled = enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable clickable stack frame links in log entries
|
||||
* @param enabled true to enable, false to disable
|
||||
*/
|
||||
public void setEnableStackFrameLinks(boolean enabled) {
|
||||
mEnableStackFrameLinks = enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the listener for stack frame click events
|
||||
* @param listener the listener to receive click events
|
||||
*/
|
||||
public void setOnStackFrameClickListener(OnStackFrameClickListener listener) {
|
||||
mStackFrameClickListener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse log content and create clickable spans for stack frames
|
||||
* @param content the original log content
|
||||
* @param baseColor the base text color
|
||||
* @return CharSequence with clickable spans for stack frames
|
||||
*/
|
||||
private CharSequence createClickableContent(CharSequence content, int baseColor) {
|
||||
if (!mEnableStackFrameLinks) {
|
||||
return content;
|
||||
}
|
||||
|
||||
String text = content.toString();
|
||||
SpannableString spannable = new SpannableString(text);
|
||||
|
||||
Matcher matcher = STACK_FRAME_PATTERN.matcher(text);
|
||||
boolean hasLinks = false;
|
||||
|
||||
while (matcher.find()) {
|
||||
hasLinks = true;
|
||||
final String fileName = matcher.group(1);
|
||||
final int lineNumber = Integer.parseInt(matcher.group(2));
|
||||
final int columnNumber = matcher.group(3) != null ? Integer.parseInt(matcher.group(3)) : 0;
|
||||
|
||||
final int start = matcher.start();
|
||||
final int end = matcher.end();
|
||||
|
||||
ClickableSpan clickableSpan = new ClickableSpan() {
|
||||
@Override
|
||||
public void onClick(@NonNull View widget) {
|
||||
if (mStackFrameClickListener != null) {
|
||||
mStackFrameClickListener.onStackFrameClick(fileName, lineNumber - 1, columnNumber);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
spannable.setSpan(clickableSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
|
||||
ForegroundColorSpan colorSpan = new ForegroundColorSpan(LINK_COLOR);
|
||||
spannable.setSpan(colorSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
}
|
||||
|
||||
return hasLinks ? spannable : content;
|
||||
}
|
||||
|
||||
protected Map<Integer, Integer> getLogLevelMap() {
|
||||
return new MapBuilder<Integer, Integer>()
|
||||
.put(Log.VERBOSE, R.color.console_view_verbose)
|
||||
@@ -323,6 +406,7 @@ public class ConsoleView extends FrameLayout implements ConsoleImpl.LogListener
|
||||
public ViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
textView = (TextView) itemView;
|
||||
textView.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -341,12 +425,18 @@ public class ConsoleView extends FrameLayout implements ConsoleImpl.LogListener
|
||||
public void onBindViewHolder(ViewHolder holder, int position) {
|
||||
TextView textView = holder.textView;
|
||||
ConsoleImpl.LogEntry logEntry = mLogEntries.get(position);
|
||||
textView.setText(logEntry.content);
|
||||
ThemeColorHelper.setThemeColorPrimary(textView, true);
|
||||
|
||||
Integer color = mColors.get(logEntry.level);
|
||||
if (color != null) {
|
||||
// Create clickable content with stack frame links
|
||||
CharSequence content = createClickableContent(logEntry.content, color);
|
||||
textView.setText(content);
|
||||
textView.setTextColor(color);
|
||||
} else {
|
||||
textView.setText(logEntry.content);
|
||||
}
|
||||
|
||||
ThemeColorHelper.setThemeColorPrimary(textView, true);
|
||||
if (textSize > 0) {
|
||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, textSize);
|
||||
} else {
|
||||
|
||||
@@ -381,10 +381,17 @@ public class ConcatReader extends Reader {
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
if (closed) return;
|
||||
IOException first = null;
|
||||
for (Reader reader : readerQueue) {
|
||||
reader.close();
|
||||
try {
|
||||
reader.close();
|
||||
} catch (IOException e) {
|
||||
if (first == null) first = e;
|
||||
else first.addSuppressed(e);
|
||||
}
|
||||
}
|
||||
closed = true;
|
||||
if (first != null) throw first;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -35,6 +35,7 @@ import org.autojs.autojs.storage.file.StableDraftFileHelper
|
||||
import org.autojs.autojs.theme.widget.ThemeColorToolbar
|
||||
import org.autojs.autojs.ui.BaseActivity
|
||||
import org.autojs.autojs.ui.error.ErrorDialogActivity
|
||||
import org.autojs.autojs.ui.log.LogBottomSheet
|
||||
import org.autojs.autojs.ui.main.MainActivity
|
||||
import org.autojs.autojs.ui.main.scripts.EditableFileInfoDialogManager
|
||||
import org.autojs.autojs.util.DialogUtils
|
||||
@@ -157,6 +158,39 @@ open class EditActivity : BaseActivity(), DelegateHost, PermissionRequestProxyAc
|
||||
|
||||
setToolbarAsBack(editorView.name)
|
||||
onBackPressedDispatcher.addCallback(this, mOnBackPressedCallback)
|
||||
|
||||
// Setup log bottom sheet
|
||||
setUpLogSheet()
|
||||
}
|
||||
|
||||
private fun setUpLogSheet() {
|
||||
mEditorView.setLogPanelCallback(object : EditorView.LogPanelCallback {
|
||||
override fun onShowLogPanel() {
|
||||
val scriptName = mEditorView.name
|
||||
val scriptPath = mEditorView.uri?.path
|
||||
|
||||
val bottomSheet = LogBottomSheet.newInstance(scriptName, scriptPath)
|
||||
bottomSheet.setOnStackFrameClickListener(object : LogBottomSheet.OnStackFrameClickListener {
|
||||
override fun onStackFrameClick(fileName: String, lineNumber: Int, columnNumber: Int) {
|
||||
// Jump to the line in editor
|
||||
try {
|
||||
val editor = mEditorView.editor
|
||||
val layout = editor.codeEditText.layout
|
||||
if (lineNumber >= 0 && lineNumber < layout.lineCount) {
|
||||
val lineStart = layout.getLineStart(lineNumber)
|
||||
val column = if (columnNumber > 0) columnNumber else 0
|
||||
val offset = minOf(lineStart + column, layout.getLineEnd(lineNumber) - 1)
|
||||
editor.codeEditText.setSelection(offset)
|
||||
editor.codeEditText.requestFocus()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
})
|
||||
bottomSheet.show(supportFragmentManager, "LogBottomSheet")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun onLoadFileError(message: String?) {
|
||||
|
||||
@@ -98,6 +98,9 @@ public class EditorMenu {
|
||||
if (itemId == R.id.action_log) {
|
||||
return ConsoleUtils.launch(mContext);
|
||||
}
|
||||
if (itemId == R.id.action_show_log) {
|
||||
return tryDoing(mEditorView::showLogPanel);
|
||||
}
|
||||
if (itemId == R.id.action_force_stop) {
|
||||
return tryDoing(mEditorView::forceStop);
|
||||
}
|
||||
@@ -160,6 +163,10 @@ public class EditorMenu {
|
||||
if (itemId == R.id.action_console) {
|
||||
return tryDoing(mEditorView::showConsole);
|
||||
}
|
||||
if (itemId == R.id.action_show_log) {
|
||||
showLogPanel();
|
||||
return true;
|
||||
}
|
||||
if (itemId == R.id.action_import_java_class) {
|
||||
importJavaPackageOrClass();
|
||||
return true;
|
||||
@@ -399,6 +406,10 @@ public class EditorMenu {
|
||||
builder.show();
|
||||
}
|
||||
|
||||
private void showLogPanel() {
|
||||
mEditorView.showLogPanel();
|
||||
}
|
||||
|
||||
private void showFileDetails() {
|
||||
Uri uri = mEditorView.getUri();
|
||||
String path;
|
||||
|
||||
@@ -127,6 +127,23 @@ import java.util.regex.Pattern
|
||||
@SuppressLint("CheckResult")
|
||||
class EditorView : LinearLayout, OnHintClickListener, ClickCallback, ToolbarFragment.OnMenuItemClickListener {
|
||||
|
||||
/**
|
||||
* Callback interface for showing the log panel from the editor
|
||||
*/
|
||||
interface LogPanelCallback {
|
||||
fun onShowLogPanel()
|
||||
}
|
||||
|
||||
private var mLogPanelCallback: LogPanelCallback? = null
|
||||
|
||||
fun setLogPanelCallback(callback: LogPanelCallback) {
|
||||
mLogPanelCallback = callback
|
||||
}
|
||||
|
||||
fun showLogPanel() {
|
||||
mLogPanelCallback?.onShowLogPanel()
|
||||
}
|
||||
|
||||
private var binding: EditorViewBinding = EditorViewBinding.bind(inflate(context, R.layout.editor_view, this))
|
||||
|
||||
@JvmField
|
||||
|
||||
115
app/src/main/java/org/autojs/autojs/ui/log/LogBottomSheet.kt
Normal file
115
app/src/main/java/org/autojs/autojs/ui/log/LogBottomSheet.kt
Normal file
@@ -0,0 +1,115 @@
|
||||
package org.autojs.autojs.ui.log
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||
import org.autojs.autojs.AutoJs
|
||||
import org.autojs.autojs6.R
|
||||
import org.autojs.autojs6.databinding.BottomSheetLogBinding
|
||||
|
||||
/**
|
||||
* Bottom sheet dialog for displaying script logs in the editor.
|
||||
* Provides quick access to log output without leaving the editor.
|
||||
* Clickable stack frames (file:line) are highlighted in blue.
|
||||
*/
|
||||
class LogBottomSheet : BottomSheetDialogFragment() {
|
||||
|
||||
private var _binding: BottomSheetLogBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
private var mScriptName: String? = null
|
||||
private var mScriptPath: String? = null
|
||||
private var mStackFrameClickListener: OnStackFrameClickListener? = null
|
||||
|
||||
interface OnStackFrameClickListener {
|
||||
fun onStackFrameClick(fileName: String, lineNumber: Int, columnNumber: Int)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val ARG_SCRIPT_NAME = "script_name"
|
||||
private const val ARG_SCRIPT_PATH = "script_path"
|
||||
|
||||
/**
|
||||
* Create a new instance with script info
|
||||
*/
|
||||
@JvmStatic
|
||||
fun newInstance(scriptName: String?, scriptPath: String?): LogBottomSheet {
|
||||
val fragment = LogBottomSheet()
|
||||
val args = Bundle()
|
||||
args.putString(ARG_SCRIPT_NAME, scriptName)
|
||||
args.putString(ARG_SCRIPT_PATH, scriptPath)
|
||||
fragment.arguments = args
|
||||
return fragment
|
||||
}
|
||||
}
|
||||
|
||||
fun setOnStackFrameClickListener(listener: OnStackFrameClickListener) {
|
||||
mStackFrameClickListener = listener
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
arguments?.let {
|
||||
mScriptName = it.getString(ARG_SCRIPT_NAME)
|
||||
mScriptPath = it.getString(ARG_SCRIPT_PATH)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = BottomSheetLogBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setupViews()
|
||||
}
|
||||
|
||||
private fun setupViews() {
|
||||
// Set title
|
||||
if (!mScriptName.isNullOrEmpty()) {
|
||||
binding.tvTitle.text = mScriptName
|
||||
}
|
||||
|
||||
// Setup ConsoleView with global console
|
||||
val autoJs = AutoJs.getInstance()
|
||||
if (autoJs != null) {
|
||||
binding.console.setConsole(autoJs.globalConsole)
|
||||
|
||||
// Hide input container (not needed in bottom sheet)
|
||||
binding.console.findViewById<View>(R.id.input_container)?.visibility = View.GONE
|
||||
|
||||
// Enable clickable stack frame links (only in bottom sheet, not in LogActivity)
|
||||
binding.console.setEnableStackFrameLinks(true)
|
||||
|
||||
// Set up clickable stack frame listener
|
||||
binding.console.setOnStackFrameClickListener { fileName, lineNumber, columnNumber ->
|
||||
mStackFrameClickListener?.onStackFrameClick(fileName, lineNumber, columnNumber)
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
// Clear button
|
||||
binding.btnClear.setOnClickListener {
|
||||
AutoJs.getInstance()?.globalConsole?.clear()
|
||||
}
|
||||
|
||||
// Open full log activity button
|
||||
binding.btnOpenFull.setOnClickListener {
|
||||
startActivity(Intent(requireContext(), LogActivity::class.java))
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
}
|
||||
10
app/src/main/res/drawable/bg_bottom_sheet_rounded.xml
Normal file
10
app/src/main/res/drawable/bg_bottom_sheet_rounded.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="?android:attr/windowBackground"/>
|
||||
<corners
|
||||
android:topLeftRadius="16dp"
|
||||
android:topRightRadius="16dp"
|
||||
android:bottomLeftRadius="0dp"
|
||||
android:bottomRightRadius="0dp"/>
|
||||
</shape>
|
||||
7
app/src/main/res/drawable/bg_drag_handle.xml
Normal file
7
app/src/main/res/drawable/bg_drag_handle.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="#DDDDDD"/>
|
||||
<corners android:radius="2dp"/>
|
||||
<size android:width="40dp" android:height="4dp"/>
|
||||
</shape>
|
||||
4
app/src/main/res/drawable/ic_clear.xml
Normal file
4
app/src/main/res/drawable/ic_clear.xml
Normal file
@@ -0,0 +1,4 @@
|
||||
<vector android:height="24dp" android:viewportHeight="200"
|
||||
android:viewportWidth="200" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF000000" android:pathData="M158.68,145.53c-4.72,4.97 -8.34,8.79 -12.38,13.05c-15.53,-15.56 -30.72,-30.76 -46.09,-46.16c-15.36,15.61 -30.56,31.05 -46.11,46.86c-4.63,-5 -8.23,-8.89 -12.16,-13.12c15.14,-15.01 30.41,-30.14 45.57,-45.17C71.76,85.33 56.39,70.07 40.7,54.48c5.16,-4.64 9.08,-8.16 13.08,-11.76c14.67,14.75 29.81,29.96 44.63,44.86c15.9,-15.95 31.17,-31.27 46.38,-46.52c5.04,5.1 8.71,8.81 12.83,12.97c-14.92,14.81 -30.26,30.04 -45.52,45.19C127.99,115.01 143.2,130.14 158.68,145.53z"/>
|
||||
</vector>
|
||||
5
app/src/main/res/drawable/ic_logcat.xml
Normal file
5
app/src/main/res/drawable/ic_logcat.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<vector android:height="24dp" android:viewportHeight="128"
|
||||
android:viewportWidth="128" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF000000" android:pathData="M95.9,22.4H85.3v-4.2c0,-2.5 -1.7,-4.2 -4.3,-4.2c-2.6,0 -4.3,1.6 -4.3,4.2v4.2H51.3v-4.2c0,-2.5 -1.7,-4.2 -4.2,-4.2c-2.5,0 -4.3,1.6 -4.3,4.2v4.2H32.1c-6,0 -10.6,4.5 -10.6,10.4v70.8c0,5.8 4.7,10.4 10.6,10.4h63.7c6,0 10.6,-4.5 10.6,-10.4V32.8C106.5,26.9 101.8,22.4 95.9,22.4zM98,103.5c0,1.3 -0.8,2.1 -2.1,2.1H32.1c-1.3,0 -2.1,-0.8 -2.1,-2.1V32.8c0,-1.3 0.8,-2.1 2.1,-2.1h10.6v4.2c0,2.5 1.7,4.2 4.2,4.2c2.5,0 4.2,-1.6 4.2,-4.2v-4.2h25.5v4.2c0,2.5 1.7,4.2 4.3,4.2c2.6,0 4.3,-1.6 4.3,-4.2v-4.2h10.6c1.3,0 2.1,0.8 2.1,2.1L98,103.5L98,103.5z"/>
|
||||
<path android:fillColor="#FF000000" android:pathData="M83.1,49.5H44.9c-2.5,0 -4.2,1.6 -4.2,4.2c0,2.5 1.7,4.2 4.2,4.2h38.2c2.5,0 4.3,-1.6 4.3,-4.2C87.4,51.1 85.7,49.5 83.1,49.5zM83.1,68.2H44.9c-2.5,0 -4.2,1.6 -4.2,4.2s1.7,4.2 4.2,4.2h38.2c2.5,0 4.3,-1.6 4.3,-4.2C87.4,69.8 85.7,68.2 83.1,68.2zM70.4,86.9H44.9c-2.5,0 -4.2,1.6 -4.2,4.2c0,2.5 1.7,4.2 4.2,4.2h25.5c2.5,0 4.2,-1.6 4.2,-4.2C74.6,88.5 73,86.9 70.4,86.9z"/>
|
||||
</vector>
|
||||
85
app/src/main/res/layout/bottom_sheet_log.xml
Normal file
85
app/src/main/res/layout/bottom_sheet_log.xml
Normal file
@@ -0,0 +1,85 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:background="@drawable/bg_bottom_sheet_rounded">
|
||||
|
||||
<!-- Drag handle -->
|
||||
<View
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="4dp"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:background="@drawable/bg_drag_handle"/>
|
||||
|
||||
<!-- Header -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="8dp">
|
||||
|
||||
<!-- Script name / Title -->
|
||||
<TextView
|
||||
android:id="@+id/tv_title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/text_log"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"/>
|
||||
|
||||
<!-- Action buttons -->
|
||||
<ImageButton
|
||||
android:id="@+id/btn_open_full"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:src="@drawable/ic_logcat"
|
||||
android:tint="?attr/colorPrimary"
|
||||
android:contentDescription="@string/text_log"
|
||||
android:scaleType="center"/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/btn_clear"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:src="@drawable/ic_clear"
|
||||
android:tint="#666666"
|
||||
android:contentDescription="@string/text_clear"
|
||||
android:scaleType="center"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Divider -->
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?android:attr/listDivider"/>
|
||||
|
||||
<!-- Console View -->
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="400dp"
|
||||
android:paddingStart="4dp">
|
||||
|
||||
<org.autojs.autojs.core.console.ConsoleView
|
||||
android:id="@+id/console"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:color_debug="@color/console_debug"
|
||||
app:color_verbose="@color/console_verbose"/>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -115,6 +115,11 @@
|
||||
android:title="@string/text_log"
|
||||
app:showAsAction="never" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_show_log"
|
||||
android:title="@string/text_show_log"
|
||||
app:showAsAction="never" />
|
||||
|
||||
<item android:title="@string/text_more">
|
||||
<menu>
|
||||
<item
|
||||
|
||||
@@ -938,6 +938,7 @@
|
||||
<string name="text_loading_with_dots" tools:ignore="TypographyEllipsis">加载中...</string>
|
||||
<string name="text_locate_current_theme_color">定位当前主题色</string>
|
||||
<string name="text_log">日志</string>
|
||||
<string name="text_show_log">显示日志</string>
|
||||
<string name="text_logging_in">登录中</string>
|
||||
<string name="text_login">登录</string>
|
||||
<string name="text_login_succeed">登录成功</string>
|
||||
|
||||
@@ -1216,6 +1216,7 @@
|
||||
<string name="text_loading_with_dots" tools:ignore="TypographyEllipsis">Loading...</string>
|
||||
<string name="text_locate_current_theme_color">Locate current theme color</string>
|
||||
<string name="text_log">Log</string>
|
||||
<string name="text_show_log">Show log</string>
|
||||
<string name="text_logging_in">Logging in</string>
|
||||
<string name="text_login">Login</string>
|
||||
<string name="text_login_succeed">Login succeeded</string>
|
||||
|
||||
@@ -346,8 +346,9 @@ pluginManagement {
|
||||
val temurin = object : Platform(
|
||||
name = "Temurin", vendor = "temurin",
|
||||
/* More common as "Eclipse Adoptium". */
|
||||
// @Updated by SuperMonster003 on Apr 16, 2025. (Manual)
|
||||
// @Updated by SuperMonster003 on Mar 15, 2026. (Manual)
|
||||
agpVersionMap = mapOf(
|
||||
"21.0.10+7" to "8.9.3", /* Mar 15, 2026. */
|
||||
"21.0.6+7" to "8.7.3", /* Apr 16, 2025. */
|
||||
"20.0.2+9" to "8.2.2", /* Dec 2, 2024. */
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user