@@ -4,6 +4,11 @@ import android.annotation.SuppressLint;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.TypedArray;
|
import android.content.res.TypedArray;
|
||||||
import android.graphics.Color;
|
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.AttributeSet;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
@@ -17,6 +22,14 @@ import androidx.annotation.NonNull;
|
|||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
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.theme.ThemeColorHelper;
|
||||||
import org.autojs.autojs.tool.MapBuilder;
|
import org.autojs.autojs.tool.MapBuilder;
|
||||||
import org.autojs.autojs.ui.log.LogActivity;
|
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.autojs.util.ViewUtils;
|
||||||
import org.autojs.autojs6.R;
|
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.
|
* Created by Stardust on May 2, 2017.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -37,6 +45,21 @@ import java.util.Objects;
|
|||||||
public class ConsoleView extends FrameLayout implements ConsoleImpl.LogListener {
|
public class ConsoleView extends FrameLayout implements ConsoleImpl.LogListener {
|
||||||
|
|
||||||
private final static int sRefreshInterval = 100;
|
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 final Map<Integer, Integer> mColors = new MapBuilder<Integer, Integer>().build();
|
||||||
private ConsoleImpl mConsole;
|
private ConsoleImpl mConsole;
|
||||||
private WeakReference<LogActivity> mLogActivity = null;
|
private WeakReference<LogActivity> mLogActivity = null;
|
||||||
@@ -228,6 +251,66 @@ public class ConsoleView extends FrameLayout implements ConsoleImpl.LogListener
|
|||||||
mIsPinchToZoomEnabled = enabled;
|
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() {
|
protected Map<Integer, Integer> getLogLevelMap() {
|
||||||
return new MapBuilder<Integer, Integer>()
|
return new MapBuilder<Integer, Integer>()
|
||||||
.put(Log.VERBOSE, R.color.console_view_verbose)
|
.put(Log.VERBOSE, R.color.console_view_verbose)
|
||||||
@@ -323,6 +406,7 @@ public class ConsoleView extends FrameLayout implements ConsoleImpl.LogListener
|
|||||||
public ViewHolder(View itemView) {
|
public ViewHolder(View itemView) {
|
||||||
super(itemView);
|
super(itemView);
|
||||||
textView = (TextView) 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) {
|
public void onBindViewHolder(ViewHolder holder, int position) {
|
||||||
TextView textView = holder.textView;
|
TextView textView = holder.textView;
|
||||||
ConsoleImpl.LogEntry logEntry = mLogEntries.get(position);
|
ConsoleImpl.LogEntry logEntry = mLogEntries.get(position);
|
||||||
textView.setText(logEntry.content);
|
|
||||||
ThemeColorHelper.setThemeColorPrimary(textView, true);
|
|
||||||
Integer color = mColors.get(logEntry.level);
|
Integer color = mColors.get(logEntry.level);
|
||||||
if (color != null) {
|
if (color != null) {
|
||||||
|
// Create clickable content with stack frame links
|
||||||
|
CharSequence content = createClickableContent(logEntry.content, color);
|
||||||
|
textView.setText(content);
|
||||||
textView.setTextColor(color);
|
textView.setTextColor(color);
|
||||||
|
} else {
|
||||||
|
textView.setText(logEntry.content);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ThemeColorHelper.setThemeColorPrimary(textView, true);
|
||||||
if (textSize > 0) {
|
if (textSize > 0) {
|
||||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, textSize);
|
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, textSize);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import org.autojs.autojs.storage.file.StableDraftFileHelper
|
|||||||
import org.autojs.autojs.theme.widget.ThemeColorToolbar
|
import org.autojs.autojs.theme.widget.ThemeColorToolbar
|
||||||
import org.autojs.autojs.ui.BaseActivity
|
import org.autojs.autojs.ui.BaseActivity
|
||||||
import org.autojs.autojs.ui.error.ErrorDialogActivity
|
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.MainActivity
|
||||||
import org.autojs.autojs.ui.main.scripts.EditableFileInfoDialogManager
|
import org.autojs.autojs.ui.main.scripts.EditableFileInfoDialogManager
|
||||||
import org.autojs.autojs.util.DialogUtils
|
import org.autojs.autojs.util.DialogUtils
|
||||||
@@ -157,6 +158,39 @@ open class EditActivity : BaseActivity(), DelegateHost, PermissionRequestProxyAc
|
|||||||
|
|
||||||
setToolbarAsBack(editorView.name)
|
setToolbarAsBack(editorView.name)
|
||||||
onBackPressedDispatcher.addCallback(this, mOnBackPressedCallback)
|
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?) {
|
private fun onLoadFileError(message: String?) {
|
||||||
|
|||||||
@@ -98,6 +98,9 @@ public class EditorMenu {
|
|||||||
if (itemId == R.id.action_log) {
|
if (itemId == R.id.action_log) {
|
||||||
return ConsoleUtils.launch(mContext);
|
return ConsoleUtils.launch(mContext);
|
||||||
}
|
}
|
||||||
|
if (itemId == R.id.action_show_log) {
|
||||||
|
return tryDoing(mEditorView::showLogPanel);
|
||||||
|
}
|
||||||
if (itemId == R.id.action_force_stop) {
|
if (itemId == R.id.action_force_stop) {
|
||||||
return tryDoing(mEditorView::forceStop);
|
return tryDoing(mEditorView::forceStop);
|
||||||
}
|
}
|
||||||
@@ -160,6 +163,10 @@ public class EditorMenu {
|
|||||||
if (itemId == R.id.action_console) {
|
if (itemId == R.id.action_console) {
|
||||||
return tryDoing(mEditorView::showConsole);
|
return tryDoing(mEditorView::showConsole);
|
||||||
}
|
}
|
||||||
|
if (itemId == R.id.action_show_log) {
|
||||||
|
showLogPanel();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (itemId == R.id.action_import_java_class) {
|
if (itemId == R.id.action_import_java_class) {
|
||||||
importJavaPackageOrClass();
|
importJavaPackageOrClass();
|
||||||
return true;
|
return true;
|
||||||
@@ -399,6 +406,10 @@ public class EditorMenu {
|
|||||||
builder.show();
|
builder.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void showLogPanel() {
|
||||||
|
mEditorView.showLogPanel();
|
||||||
|
}
|
||||||
|
|
||||||
private void showFileDetails() {
|
private void showFileDetails() {
|
||||||
Uri uri = mEditorView.getUri();
|
Uri uri = mEditorView.getUri();
|
||||||
String path;
|
String path;
|
||||||
|
|||||||
@@ -127,6 +127,23 @@ import java.util.regex.Pattern
|
|||||||
@SuppressLint("CheckResult")
|
@SuppressLint("CheckResult")
|
||||||
class EditorView : LinearLayout, OnHintClickListener, ClickCallback, ToolbarFragment.OnMenuItemClickListener {
|
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))
|
private var binding: EditorViewBinding = EditorViewBinding.bind(inflate(context, R.layout.editor_view, this))
|
||||||
|
|
||||||
@JvmField
|
@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"
|
android:title="@string/text_log"
|
||||||
app:showAsAction="never" />
|
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">
|
<item android:title="@string/text_more">
|
||||||
<menu>
|
<menu>
|
||||||
<item
|
<item
|
||||||
|
|||||||
@@ -938,6 +938,7 @@
|
|||||||
<string name="text_loading_with_dots" tools:ignore="TypographyEllipsis">加载中...</string>
|
<string name="text_loading_with_dots" tools:ignore="TypographyEllipsis">加载中...</string>
|
||||||
<string name="text_locate_current_theme_color">定位当前主题色</string>
|
<string name="text_locate_current_theme_color">定位当前主题色</string>
|
||||||
<string name="text_log">日志</string>
|
<string name="text_log">日志</string>
|
||||||
|
<string name="text_show_log">显示日志</string>
|
||||||
<string name="text_logging_in">登录中</string>
|
<string name="text_logging_in">登录中</string>
|
||||||
<string name="text_login">登录</string>
|
<string name="text_login">登录</string>
|
||||||
<string name="text_login_succeed">登录成功</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_loading_with_dots" tools:ignore="TypographyEllipsis">Loading...</string>
|
||||||
<string name="text_locate_current_theme_color">Locate current theme color</string>
|
<string name="text_locate_current_theme_color">Locate current theme color</string>
|
||||||
<string name="text_log">Log</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_logging_in">Logging in</string>
|
||||||
<string name="text_login">Login</string>
|
<string name="text_login">Login</string>
|
||||||
<string name="text_login_succeed">Login succeeded</string>
|
<string name="text_login_succeed">Login succeeded</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user