6.4.0 - 新增 barcode/qrcode/shizuku 等模块; 适配高版本系统语言设置; 优化打包功能; 支持应用快捷方式; 修复屏幕旋转相关问题
This commit is contained in:
@@ -2,6 +2,8 @@ package org.autojs.autojs.core.console;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Color;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
@@ -57,29 +59,53 @@ public class ConsoleView extends FrameLayout implements ConsoleImpl.LogListener
|
||||
|
||||
public ConsoleView(Context context) {
|
||||
super(context);
|
||||
init();
|
||||
init(null);
|
||||
}
|
||||
|
||||
public ConsoleView(Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
init(attrs);
|
||||
}
|
||||
|
||||
public ConsoleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init();
|
||||
init(attrs);
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
private void init() {
|
||||
private void init(@Nullable AttributeSet attrs) {
|
||||
inflate(getContext(), R.layout.console_view, this);
|
||||
|
||||
for (Map.Entry<Integer, Integer> map : getLogLevelMap().entrySet()) {
|
||||
Map<Integer, Integer> logLevelColorResIdMap = getLogLevelMap();
|
||||
Map<Integer, Integer> logLevelColorIntMap = getLogLevelMap();
|
||||
|
||||
if (attrs != null) {
|
||||
TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.ConsoleView);
|
||||
|
||||
logLevelColorIntMap.put(Log.VERBOSE, ta.getColor(R.styleable.ConsoleView_color_verbose, Color.TRANSPARENT));
|
||||
logLevelColorIntMap.put(Log.DEBUG, ta.getColor(R.styleable.ConsoleView_color_debug, Color.TRANSPARENT));
|
||||
logLevelColorIntMap.put(Log.INFO, ta.getColor(R.styleable.ConsoleView_color_info, Color.TRANSPARENT));
|
||||
logLevelColorIntMap.put(Log.WARN, ta.getColor(R.styleable.ConsoleView_color_warn, Color.TRANSPARENT));
|
||||
logLevelColorIntMap.put(Log.ERROR, ta.getColor(R.styleable.ConsoleView_color_error, Color.TRANSPARENT));
|
||||
logLevelColorIntMap.put(Log.ASSERT, ta.getColor(R.styleable.ConsoleView_color_assert, Color.TRANSPARENT));
|
||||
|
||||
ta.recycle();
|
||||
}
|
||||
|
||||
for (Map.Entry<Integer, Integer> map : logLevelColorResIdMap.entrySet()) {
|
||||
int logLevel = map.getKey();
|
||||
int colorResKey = map.getValue();
|
||||
mColors.put(logLevel, getContext().getColor(colorResKey));
|
||||
}
|
||||
|
||||
for (Map.Entry<Integer, Integer> map : logLevelColorIntMap.entrySet()) {
|
||||
int logLevel = map.getKey();
|
||||
int colorInt = map.getValue();
|
||||
if (colorInt != Color.TRANSPARENT) {
|
||||
mColors.put(logLevel, colorInt);
|
||||
}
|
||||
}
|
||||
|
||||
ScaleGestureDetector mScaleGestureDetector = new ScaleGestureDetector(getContext(), getSimpleOnScaleGestureListener());
|
||||
|
||||
mLogListRecyclerView = findViewById(R.id.log_list);
|
||||
@@ -166,24 +192,28 @@ public class ConsoleView extends FrameLayout implements ConsoleImpl.LogListener
|
||||
adapter.setDebugTextColor(color);
|
||||
}
|
||||
}
|
||||
|
||||
public void setInfoTextColor(int color) {
|
||||
Adapter adapter = (Adapter) mLogListRecyclerView.getAdapter();
|
||||
if (adapter != null) {
|
||||
adapter.setInfoTextColor(color);
|
||||
}
|
||||
}
|
||||
|
||||
public void setWarnTextColor(int color) {
|
||||
Adapter adapter = (Adapter) mLogListRecyclerView.getAdapter();
|
||||
if (adapter != null) {
|
||||
adapter.setWarnTextColor(color);
|
||||
}
|
||||
}
|
||||
|
||||
public void setErrorTextColor(int color) {
|
||||
Adapter adapter = (Adapter) mLogListRecyclerView.getAdapter();
|
||||
if (adapter != null) {
|
||||
adapter.setErrorTextColor(color);
|
||||
}
|
||||
}
|
||||
|
||||
public void setAssertTextColor(int color) {
|
||||
Adapter adapter = (Adapter) mLogListRecyclerView.getAdapter();
|
||||
if (adapter != null) {
|
||||
@@ -319,7 +349,7 @@ public class ConsoleView extends FrameLayout implements ConsoleImpl.LogListener
|
||||
public void showEditText() {
|
||||
post(() -> {
|
||||
mWindow.requestWindowFocus();
|
||||
//mInputContainer.setVisibility(VISIBLE);
|
||||
// mInputContainer.setVisibility(VISIBLE);
|
||||
mEditText.requestFocus();
|
||||
});
|
||||
}
|
||||
@@ -359,7 +389,7 @@ public class ConsoleView extends FrameLayout implements ConsoleImpl.LogListener
|
||||
if (textSize > 0) {
|
||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, textSize);
|
||||
} else {
|
||||
textSize = DisplayUtils.pxToSp(getContext(), textView.getTextSize());
|
||||
textSize = DisplayUtils.pxToSp(textView.getTextSize());
|
||||
}
|
||||
textView.setClickable(false);
|
||||
textView.setLongClickable(false);
|
||||
|
||||
@@ -19,12 +19,12 @@ class FloatingConsoleView : ConsoleView {
|
||||
}
|
||||
|
||||
override fun getLogLevelMap(): MutableMap<Int, Int> = MapBuilder<Int, Int>()
|
||||
.put(Log.VERBOSE,R.color.floating_console_view_verbose)
|
||||
.put(Log.DEBUG,R.color.floating_console_view_debug)
|
||||
.put(Log.INFO,R.color.floating_console_view_info)
|
||||
.put(Log.WARN,R.color.floating_console_view_warn)
|
||||
.put(Log.ERROR,R.color.floating_console_view_error)
|
||||
.put(Log.ASSERT,R.color.floating_console_view_assert)
|
||||
.put(Log.VERBOSE, R.color.floating_console_view_verbose)
|
||||
.put(Log.DEBUG, R.color.floating_console_view_debug)
|
||||
.put(Log.INFO, R.color.floating_console_view_info)
|
||||
.put(Log.WARN, R.color.floating_console_view_warn)
|
||||
.put(Log.ERROR, R.color.floating_console_view_error)
|
||||
.put(Log.ASSERT, R.color.floating_console_view_assert)
|
||||
.build()
|
||||
|
||||
}
|
||||
@@ -8,8 +8,6 @@ import static android.util.Log.VERBOSE;
|
||||
import static android.util.Log.WARN;
|
||||
import static android.util.Log.d;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.apache.log4j.Level;
|
||||
@@ -24,11 +22,10 @@ import java.util.Locale;
|
||||
/**
|
||||
* Created by Stardust on 2017/10/22.
|
||||
*/
|
||||
@SuppressLint("ConstantLocale")
|
||||
public class GlobalConsole extends ConsoleImpl {
|
||||
private static final String TAG = GlobalConsole.class.getSimpleName();
|
||||
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("HH:mm:ss.SSS", Locale.getDefault());
|
||||
private static final Logger LOGGER = Logger.getLogger(GlobalConsole.class);
|
||||
private final SimpleDateFormat mDateFormat = new SimpleDateFormat("HH:mm:ss.SSS", Locale.getDefault());
|
||||
|
||||
public GlobalConsole(UiHandler uiHandler) {
|
||||
super(uiHandler);
|
||||
@@ -38,7 +35,7 @@ public class GlobalConsole extends ConsoleImpl {
|
||||
@NonNull
|
||||
public String println(int level, @NonNull CharSequence charSequence) {
|
||||
String log = String.format(Locale.getDefault(), "%s/%s: %s",
|
||||
DATE_FORMAT.format(new Date()), getLevelChar(level), charSequence);
|
||||
mDateFormat.format(new Date()), getLevelChar(level), charSequence);
|
||||
LOGGER.log(toLog4jLevel(level), log);
|
||||
d(TAG, log);
|
||||
super.println(level, log);
|
||||
|
||||
@@ -31,7 +31,6 @@ public class EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class Listeners {
|
||||
private final CopyOnWriteArrayList<ListenerWrapper> mListenerWrappers = new CopyOnWriteArrayList<>();
|
||||
|
||||
@@ -134,8 +133,9 @@ public class EventEmitter {
|
||||
|
||||
public boolean emit(String eventName, Object... args) {
|
||||
Listeners listeners = mListenersMap.get(eventName);
|
||||
if (listeners == null || listeners.empty())
|
||||
if (listeners == null || listeners.empty()) {
|
||||
return false;
|
||||
}
|
||||
listeners.emit(args);
|
||||
return true;
|
||||
}
|
||||
@@ -146,8 +146,9 @@ public class EventEmitter {
|
||||
|
||||
public int listenerCount(String eventName) {
|
||||
Listeners listeners = mListenersMap.get(eventName);
|
||||
if (listeners == null)
|
||||
if (listeners == null) {
|
||||
return 0;
|
||||
}
|
||||
return listeners.count();
|
||||
}
|
||||
|
||||
@@ -177,8 +178,9 @@ public class EventEmitter {
|
||||
|
||||
public EventEmitter removeListener(String eventName, Object listener) {
|
||||
Listeners listeners = mListenersMap.get(eventName);
|
||||
if (listeners != null)
|
||||
if (listeners != null) {
|
||||
listeners.remove(listener);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -195,5 +197,4 @@ public class EventEmitter {
|
||||
return defaultMaxListeners;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -20,12 +20,12 @@ import android.view.OrientationEventListener;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.autojs.autojs.lang.ThreadCompat;
|
||||
import org.autojs.autojs.runtime.ScriptRuntime;
|
||||
import org.autojs.autojs.runtime.api.ScreenMetrics;
|
||||
import org.autojs.autojs.runtime.exception.ScriptException;
|
||||
import org.autojs.autojs.runtime.exception.ScriptInterruptedException;
|
||||
import org.autojs.autojs.util.ForegroundServiceUtils;
|
||||
import org.autojs.autojs.lang.ThreadCompat;
|
||||
import org.autojs.autojs.runtime.api.ScreenMetrics;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
||||
@@ -45,6 +45,7 @@ class NotificationListenerService : android.service.notification.NotificationLis
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
var instance: NotificationListenerService? = null
|
||||
private set
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.util.Log
|
||||
import org.apache.log4j.Logger
|
||||
import org.autojs.autojs.AutoJs
|
||||
import org.autojs.autojs.core.console.ConsoleImpl
|
||||
import org.autojs.autojs.core.console.ConsoleView
|
||||
import org.autojs.autojs.core.console.GlobalConsole
|
||||
@@ -22,22 +23,24 @@ class JsConsoleView : ConsoleView {
|
||||
|
||||
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
|
||||
|
||||
// init {
|
||||
// setConsole(object : GlobalConsole(UiHandler(context)) {
|
||||
// override fun println(level: Int, charSequence: CharSequence): String {
|
||||
// val log = String.format(Locale.getDefault(), "%s", charSequence)
|
||||
// LOGGER.log(toLog4jLevel(level), log)
|
||||
// Log.d(TAG, log)
|
||||
// super.println(level, log)
|
||||
// return log
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
//
|
||||
// override fun onNewLog(logEntry: ConsoleImpl.LogEntry?) {
|
||||
// if (logEntry != null) {
|
||||
// ViewUtils.showToast(context, logEntry.content.toString())
|
||||
// }
|
||||
// }
|
||||
init {
|
||||
// setConsole(object : GlobalConsole(UiHandler(context)) {
|
||||
// override fun println(level: Int, charSequence: CharSequence): String {
|
||||
// val log = String.format(Locale.getDefault(), "%s", charSequence)
|
||||
// LOGGER.log(toLog4jLevel(level), log)
|
||||
// Log.d(TAG, log)
|
||||
// super.println(level, log)
|
||||
// return log
|
||||
// }
|
||||
// })
|
||||
setConsole(AutoJs.instance.globalConsole)
|
||||
}
|
||||
|
||||
override fun onNewLog(logEntry: ConsoleImpl.LogEntry?) {
|
||||
// if (logEntry != null) {
|
||||
// ViewUtils.showToast(context, logEntry.content.toString())
|
||||
// }
|
||||
super.onNewLog(logEntry)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -48,7 +48,7 @@ public class TaskerScriptEditActivity extends BaseActivity {
|
||||
ViewUtils.showToast(TaskerScriptEditActivity.this, ex.getMessage(), true);
|
||||
finish();
|
||||
});
|
||||
setToolbarAsBack(mEditorView.getName());
|
||||
setToolbarAsBack(mEditorView.name);
|
||||
}
|
||||
|
||||
public static void edit(Activity activity, String title, String summary, String content) {
|
||||
@@ -61,9 +61,7 @@ public class TaskerScriptEditActivity extends BaseActivity {
|
||||
@Override
|
||||
public void finish() {
|
||||
CodeEditor editor = mEditorView.editor;
|
||||
if (editor != null) {
|
||||
setResult(RESULT_OK, new Intent().putExtra(EXTRA_CONTENT, editor.getText()));
|
||||
}
|
||||
setResult(RESULT_OK, new Intent().putExtra(EXTRA_CONTENT, editor.getText()));
|
||||
TaskerScriptEditActivity.super.finish();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,23 +1,24 @@
|
||||
package org.autojs.autojs.inrt
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.annotation.Nullable
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import org.autojs.autojs6.R
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/12/8.
|
||||
* Modified by SuperMonster003 as of Oct 27, 2023.
|
||||
*/
|
||||
class SettingsActivity : AppCompatActivity() {
|
||||
override fun onCreate(@Nullable savedInstanceState: Bundle?) {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setupViews()
|
||||
}
|
||||
|
||||
private fun setupViews() {
|
||||
setContentView(R.layout.activity_settings_inrt)
|
||||
fragmentManager.beginTransaction().replace(R.id.fragment_setting, PreferenceFragment()).commit()
|
||||
supportFragmentManager.beginTransaction().replace(R.id.fragment_setting, PreferenceFragment()).commit()
|
||||
val toolbar = findViewById<Toolbar>(R.id.toolbar)
|
||||
toolbar.setTitle(R.string.text_settings)
|
||||
setSupportActionBar(toolbar)
|
||||
@@ -25,14 +26,10 @@ class SettingsActivity : AppCompatActivity() {
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
}
|
||||
|
||||
class PreferenceFragment : androidx.preference.PreferenceFragment() {
|
||||
|
||||
override fun onCreate(@Nullable savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
}
|
||||
|
||||
class PreferenceFragment : androidx.preference.PreferenceFragmentCompat() {
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
addPreferencesFromResource(R.xml.preference_inrt)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -34,11 +34,9 @@ class SplashActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
private fun main() {
|
||||
checkPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
||||
Manifest.permission.READ_PHONE_STATE)
|
||||
checkPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||
}
|
||||
|
||||
|
||||
private fun runScript() {
|
||||
Thread {
|
||||
try {
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package org.autojs.autojs.permission
|
||||
|
||||
import android.content.Context
|
||||
import org.autojs.autojs.runtime.api.WrappedShizuku
|
||||
import org.autojs.autojs.ui.main.drawer.PermissionItemHelper
|
||||
import org.autojs.autojs.util.ViewUtils
|
||||
import org.autojs.autojs6.R
|
||||
import rikka.shizuku.Shizuku
|
||||
|
||||
class ShizukuPermission(override val context: Context) : PermissionItemHelper {
|
||||
|
||||
override fun has() = WrappedShizuku.hasPermission()
|
||||
|
||||
override fun request() {
|
||||
when {
|
||||
!WrappedShizuku.isInstalled() -> ViewUtils.showToast(context, R.string.error_shizuku_is_not_installed)
|
||||
Shizuku.isPreV11() -> ViewUtils.showToast(context, R.string.error_shizuku_version_is_not_supported)
|
||||
else -> {
|
||||
try {
|
||||
if (!Shizuku.shouldShowRequestPermissionRationale()) {
|
||||
WrappedShizuku.requestPermission()
|
||||
return
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
WrappedShizuku.config(true) ?: ViewUtils.showToast(context, R.string.error_failed_to_grant_shizuku_access)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun revoke() {
|
||||
when {
|
||||
!WrappedShizuku.isInstalled() -> ViewUtils.showToast(context, R.string.error_shizuku_is_not_installed)
|
||||
Shizuku.isPreV11() -> ViewUtils.showToast(context, R.string.error_shizuku_version_is_not_supported)
|
||||
else -> WrappedShizuku.config(false) ?: ViewUtils.showToast(context, R.string.error_failed_to_revoke_shizuku_access)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -104,8 +104,9 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver
|
||||
}
|
||||
|
||||
public void observeKey() {
|
||||
if (mListeningKey)
|
||||
if (mListeningKey) {
|
||||
return;
|
||||
}
|
||||
AccessibilityService service = getAccessibilityService();
|
||||
|
||||
// @Dubious by SuperMonster003 on Feb 11, 2022.
|
||||
@@ -129,8 +130,9 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver
|
||||
}
|
||||
|
||||
public void observeTouch() {
|
||||
if (mTouchObserver != null)
|
||||
if (mTouchObserver != null) {
|
||||
return;
|
||||
}
|
||||
ensureHandler();
|
||||
mLoopers.waitWhenIdle(true);
|
||||
mTouchObserver = new TouchObserver(InputEventObserver.initObserver(mContext));
|
||||
@@ -155,11 +157,13 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver
|
||||
}
|
||||
|
||||
private void ensureKeyInterceptor() {
|
||||
if (mKeyInterceptor != null)
|
||||
if (mKeyInterceptor != null) {
|
||||
return;
|
||||
}
|
||||
mKeyInterceptor = event -> {
|
||||
if (mInterceptsAllKey)
|
||||
if (mInterceptsAllKey) {
|
||||
return true;
|
||||
}
|
||||
String keyName = KeyEvent.keyCodeToString(event.getKeyCode()).substring(8).toLowerCase(Language.getPrefLanguage().getLocale());
|
||||
return mInterceptedKeys.contains(keyName);
|
||||
};
|
||||
@@ -169,12 +173,12 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver
|
||||
private AccessibilityService getAccessibilityService() {
|
||||
mScriptRuntime.ensureAccessibilityServiceEnabled();
|
||||
AccessibilityService service = mAccessibilityBridge.getService();
|
||||
if (service == null)
|
||||
if (service == null) {
|
||||
throw new ScriptException(mContext.getString(R.string.error_no_accessibility_service));
|
||||
}
|
||||
return service;
|
||||
}
|
||||
|
||||
|
||||
public Events onKeyDown(String keyName, Object listener) {
|
||||
on(PREFIX_KEY_DOWN + keyName, listener);
|
||||
return this;
|
||||
@@ -224,21 +228,35 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver
|
||||
}
|
||||
|
||||
public void observeNotification() {
|
||||
if (mListeningNotification)
|
||||
if (mListeningNotification) {
|
||||
return;
|
||||
}
|
||||
mListeningNotification = true;
|
||||
ensureHandler();
|
||||
mLoopers.waitWhenIdle(true);
|
||||
if (NotificationListenerService.Companion.getInstance() == null) {
|
||||
mContext.startActivity(new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS));
|
||||
throw new ScriptException(mContext.getString(R.string.text_notification_service_disabled));
|
||||
if (NotificationListenerService.getInstance() != null) {
|
||||
NotificationListenerService.getInstance().addListener(this);
|
||||
return;
|
||||
}
|
||||
NotificationListenerService.Companion.getInstance().addListener(this);
|
||||
Intent intent = new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
mContext.startActivity(intent);
|
||||
throw new ScriptException(mContext.getString(R.string.text_notification_service_disabled));
|
||||
}
|
||||
|
||||
public void removeNotificationObserver() {
|
||||
mAccessibilityBridge.getNotificationObserver().removeNotificationListener(this);
|
||||
if (NotificationListenerService.getInstance() != null) {
|
||||
NotificationListenerService.getInstance().removeListener(this);
|
||||
}
|
||||
mListeningNotification = false;
|
||||
mLoopers.waitWhenIdle(mListeningToast);
|
||||
}
|
||||
|
||||
public void observeToast() {
|
||||
if (mListeningToast)
|
||||
if (mListeningToast) {
|
||||
return;
|
||||
}
|
||||
mAccessibilityBridge.ensureServiceEnabled();
|
||||
mListeningToast = true;
|
||||
ensureHandler();
|
||||
@@ -246,6 +264,14 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver
|
||||
mAccessibilityBridge.getNotificationObserver().addToastListener(this);
|
||||
}
|
||||
|
||||
public void removeToastObserver() {
|
||||
mAccessibilityBridge.getNotificationObserver().removeToastListener(this);
|
||||
if (NotificationListenerService.getInstance() != null) {
|
||||
NotificationListenerService.getInstance().removeListener(this);
|
||||
}
|
||||
mListeningToast = false;
|
||||
mLoopers.waitWhenIdle(mListeningNotification);
|
||||
}
|
||||
|
||||
public Events onNotification(Object listener) {
|
||||
on("notification", listener);
|
||||
@@ -271,11 +297,10 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver
|
||||
mTouchObserver.stop();
|
||||
}
|
||||
if (mListeningNotification) {
|
||||
mAccessibilityBridge.getNotificationObserver().removeNotificationListener(this);
|
||||
mAccessibilityBridge.getNotificationObserver().removeToastListener(this);
|
||||
if (NotificationListenerService.Companion.getInstance() != null) {
|
||||
NotificationListenerService.Companion.getInstance().removeListener(this);
|
||||
}
|
||||
removeNotificationObserver();
|
||||
}
|
||||
if (mListeningToast) {
|
||||
removeToastObserver();
|
||||
}
|
||||
if (mKeyInterceptor != null) {
|
||||
AccessibilityService service = mAccessibilityBridge.getService();
|
||||
@@ -284,6 +309,7 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver
|
||||
}
|
||||
mKeyInterceptor = null;
|
||||
}
|
||||
mLoopers.waitWhenIdle(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -313,7 +339,6 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver
|
||||
|
||||
public void onNotification(@NonNull final Notification notification) {
|
||||
mHandler.post(() -> emit("notification", notification));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -24,34 +24,34 @@ class ScreenMetrics(private var designWidth: Int, private var designHeight: Int)
|
||||
|
||||
@JvmOverloads
|
||||
fun scaleX(x: Int, width: Int = designWidth) = when {
|
||||
width == 0 || !isInitialized -> x
|
||||
width == 0 || !mIsInitialized -> x
|
||||
else -> x * deviceScreenWidth / width
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun scaleY(y: Int, height: Int = designHeight) = when {
|
||||
height == 0 || !isInitialized -> y
|
||||
height == 0 || !mIsInitialized -> y
|
||||
else -> y * deviceScreenHeight / height
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun rescaleX(x: Int, width: Int = designWidth) = when {
|
||||
width == 0 || !isInitialized -> x
|
||||
width == 0 || !mIsInitialized -> x
|
||||
else -> x * width / deviceScreenWidth
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun rescaleY(y: Int, height: Int = designHeight) = when {
|
||||
height == 0 || !isInitialized -> y
|
||||
height == 0 || !mIsInitialized -> y
|
||||
else -> y * height / deviceScreenHeight
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private var mWindowManager: WindowManager? = null
|
||||
private var mResources: Resources? = null
|
||||
var resources: Resources? = null
|
||||
|
||||
private var isInitialized = false
|
||||
private var mWindowManager: WindowManager? = null
|
||||
private var mIsInitialized = false
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
@JvmStatic
|
||||
@@ -60,7 +60,7 @@ class ScreenMetrics(private var designWidth: Int, private var designHeight: Int)
|
||||
|
||||
@JvmStatic
|
||||
val orientation: Int
|
||||
get() = mResources?.configuration?.orientation ?: ORIENTATION_PORTRAIT
|
||||
get() = resources?.configuration?.orientation ?: ORIENTATION_PORTRAIT
|
||||
|
||||
@JvmStatic
|
||||
val isScreenPortrait: Boolean
|
||||
@@ -74,7 +74,7 @@ class ScreenMetrics(private var designWidth: Int, private var designHeight: Int)
|
||||
@Suppress("DEPRECATION")
|
||||
val deviceScreenWidth: Int
|
||||
get() {
|
||||
mResources?.displayMetrics?.widthPixels?.takeIf { it > 0 }?.let { return it }
|
||||
resources?.displayMetrics?.widthPixels?.takeIf { it > 0 }?.let { return it }
|
||||
|
||||
val metricsLegacy = DisplayMetrics()
|
||||
val display = mWindowManager?.defaultDisplay?.apply { getRealMetrics(metricsLegacy) }
|
||||
@@ -89,7 +89,7 @@ class ScreenMetrics(private var designWidth: Int, private var designHeight: Int)
|
||||
@Suppress("DEPRECATION")
|
||||
val deviceScreenHeight: Int
|
||||
get() {
|
||||
mResources?.displayMetrics?.heightPixels?.takeIf { it > 0 }?.let { return it }
|
||||
resources?.displayMetrics?.heightPixels?.takeIf { it > 0 }?.let { return it }
|
||||
|
||||
val metricsLegacy = DisplayMetrics()
|
||||
val display = mWindowManager?.defaultDisplay?.apply { getRealMetrics(metricsLegacy) }
|
||||
@@ -111,9 +111,9 @@ class ScreenMetrics(private var designWidth: Int, private var designHeight: Int)
|
||||
|
||||
@JvmStatic
|
||||
fun init(activity: Activity) {
|
||||
resources = activity.resources
|
||||
mWindowManager = activity.windowManager
|
||||
mResources = activity.resources
|
||||
isInitialized = true
|
||||
mIsInitialized = true
|
||||
}
|
||||
|
||||
private fun toOriAwarePoint(a: Int, b: Int) = arrayOf(minOf(a, b), maxOf(a, b))
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
package org.autojs.autojs.runtime.api
|
||||
|
||||
import android.content.ComponentName
|
||||
import android.content.Intent
|
||||
import android.content.ServiceConnection
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.IBinder
|
||||
import android.util.Log
|
||||
import org.autojs.autojs.App
|
||||
import org.autojs.autojs.annotation.ScriptInterface
|
||||
import org.autojs.autojs.app.GlobalAppContext
|
||||
import org.autojs.autojs.core.shizuku.IUserService
|
||||
import org.autojs.autojs.core.shizuku.UserService
|
||||
import org.autojs.autojs.util.ViewUtils
|
||||
import org.autojs.autojs6.BuildConfig
|
||||
import org.autojs.autojs6.R
|
||||
import rikka.shizuku.Shizuku
|
||||
import org.autojs.autojs.runtime.api.AbstractShell.Result as ShellResult
|
||||
|
||||
@@ -23,6 +27,9 @@ object WrappedShizuku {
|
||||
|
||||
private val TAG: String = WrappedShizuku::class.java.simpleName
|
||||
|
||||
private val context
|
||||
get() = GlobalAppContext.get()
|
||||
|
||||
private val mRequestCode = "shizuku-request-code".hashCode()
|
||||
|
||||
private val mUserServiceConnection: ServiceConnection = object : ServiceConnection {
|
||||
@@ -36,7 +43,7 @@ object WrappedShizuku {
|
||||
}
|
||||
|
||||
override fun onServiceDisconnected(componentName: ComponentName) {
|
||||
// ... ...
|
||||
Log.d(TAG, "onServiceDisconnected: ${componentName.className}")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,16 +53,16 @@ object WrappedShizuku {
|
||||
.debuggable(BuildConfig.DEBUG)
|
||||
.version(BuildConfig.VERSION_CODE)
|
||||
|
||||
private val mBinderReceivedListener = {
|
||||
// if (Shizuku.isPreV11()) {
|
||||
// binding.text1.setText("Shizuku pre-v11 is not supported")
|
||||
// } else {
|
||||
// binding.text1.setText("Binder received")
|
||||
// }
|
||||
private val mBinderReceivedListener = Shizuku.OnBinderReceivedListener {
|
||||
if (Shizuku.isPreV11()) {
|
||||
Log.d(TAG, "Shizuku pre-v11 is not supported")
|
||||
} else {
|
||||
Log.d(TAG, "Binder received")
|
||||
}
|
||||
}
|
||||
|
||||
private val mBinderDeadListener = {
|
||||
// binding.text1.setText("Binder dead")
|
||||
private val mBinderDeadListener = Shizuku.OnBinderDeadListener {
|
||||
Log.d(TAG, "Binder dead")
|
||||
}
|
||||
|
||||
private val mRequestPermissionResultListener: (requestCode: Int, grantResult: Int) -> Unit = { requestCode: Int, grantResult: Int ->
|
||||
@@ -71,53 +78,65 @@ object WrappedShizuku {
|
||||
Shizuku.addRequestPermissionResultListener(mRequestPermissionResultListener)
|
||||
}
|
||||
|
||||
internal fun bindUserServiceIfNeeded() {
|
||||
if (hasPermission()) {
|
||||
bindUserService()
|
||||
}
|
||||
}
|
||||
|
||||
private fun bindUserService() {
|
||||
val res = StringBuilder()
|
||||
try {
|
||||
if (Shizuku.getVersion() < 10) {
|
||||
res.append("requires Shizuku API 10")
|
||||
} else {
|
||||
if (!Shizuku.isPreV11()) {
|
||||
Shizuku.bindUserService(mUserServiceArgs, mUserServiceConnection)
|
||||
}
|
||||
} catch (tr: Throwable) {
|
||||
tr.printStackTrace()
|
||||
res.append(tr)
|
||||
} catch (e: Throwable) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
// binding.text3.setText(res.toString().trim { it <= ' ' })
|
||||
}
|
||||
|
||||
private fun unbindUserService() {
|
||||
val res = StringBuilder()
|
||||
try {
|
||||
if (Shizuku.getVersion() < 10) {
|
||||
res.append("requires Shizuku API 10")
|
||||
} else {
|
||||
if (!Shizuku.isPreV11()) {
|
||||
Shizuku.unbindUserService(mUserServiceArgs, mUserServiceConnection, true)
|
||||
}
|
||||
} catch (tr: Throwable) {
|
||||
tr.printStackTrace()
|
||||
res.append(tr)
|
||||
} catch (_: Throwable) {
|
||||
// Ignored.
|
||||
}
|
||||
// binding.text3.setText(res.toString().trim { it <= ' ' })
|
||||
}
|
||||
|
||||
internal fun checkShizukuPermission() = try {
|
||||
when {
|
||||
Shizuku.isPreV11() -> false
|
||||
Shizuku.checkSelfPermission() == PackageManager.PERMISSION_GRANTED -> true.also { bindUserService() }
|
||||
Shizuku.shouldShowRequestPermissionRationale() -> false
|
||||
else -> false.also { Shizuku.requestPermission(mRequestCode) }
|
||||
}
|
||||
@ScriptInterface
|
||||
fun isInstalled() = getLaunchIntent() != null
|
||||
|
||||
@ScriptInterface
|
||||
fun hasPermission() = try {
|
||||
Shizuku.checkSelfPermission() == PackageManager.PERMISSION_GRANTED
|
||||
} catch (e: Throwable) {
|
||||
false.also { e.printStackTrace() }
|
||||
}
|
||||
|
||||
@ScriptInterface
|
||||
fun requestPermission() = Shizuku.requestPermission(mRequestCode)
|
||||
|
||||
@ScriptInterface
|
||||
@JvmOverloads
|
||||
fun config(isRequest: Boolean? = null): Intent? {
|
||||
return getLaunchIntent()?.also {
|
||||
context.startActivity(it)
|
||||
val message = when (isRequest) {
|
||||
true -> "${context.getString(R.string.text_grant_autojs6_access_in_shizuku_app)} (${context.getString(R.string.text_shizuku_service_may_need_to_be_run_first)})"
|
||||
false -> context.getString(R.string.text_revoke_autojs6_access_in_shizuku_app)
|
||||
else -> null
|
||||
}
|
||||
ViewUtils.showToast(context, message, true)
|
||||
}
|
||||
}
|
||||
|
||||
@ScriptInterface
|
||||
fun execCommand(cmd: String): ShellResult {
|
||||
ensureService()
|
||||
return try {
|
||||
ShellResult.fromJson(service!!.execCommand(cmd))
|
||||
} catch (e: Exception) {
|
||||
} catch (e: Throwable) {
|
||||
ShellResult().apply {
|
||||
code = 1
|
||||
error = e.message ?: ""
|
||||
@@ -133,7 +152,7 @@ object WrappedShizuku {
|
||||
|
||||
@ScriptInterface
|
||||
fun ensureService() {
|
||||
service ?: throw IllegalStateException("Shizuku service is not available")
|
||||
service ?: throw IllegalStateException(context.getString(R.string.error_unable_to_use_shizuku_service))
|
||||
}
|
||||
|
||||
internal fun onDestroy() {
|
||||
@@ -143,4 +162,10 @@ object WrappedShizuku {
|
||||
Shizuku.removeRequestPermissionResultListener(mRequestPermissionResultListener)
|
||||
}
|
||||
|
||||
private fun getLaunchIntent(): Intent? {
|
||||
return context.packageManager.getLaunchIntentForPackage(org.autojs.autojs.util.App.SHIZUKU.packageName)?.apply {
|
||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,13 +3,13 @@ package org.autojs.autojs.service
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.provider.Settings
|
||||
import org.autojs.autojs.core.notification.NotificationListenerService.Companion.instance
|
||||
import org.autojs.autojs.core.notification.NotificationListenerService
|
||||
import org.autojs.autojs.ui.main.drawer.ServiceItemHelper
|
||||
|
||||
class NotificationService(override val context: Context) : ServiceItemHelper {
|
||||
|
||||
override val isRunning: Boolean
|
||||
get() = instance != null
|
||||
get() = NotificationListenerService.instance != null
|
||||
|
||||
override fun start() {
|
||||
config()
|
||||
|
||||
@@ -193,7 +193,7 @@ open class EditActivity : BaseActivity(), DelegateHost, PermissionRequestProxyAc
|
||||
if (!mEditorView.isTextChanged) {
|
||||
return
|
||||
}
|
||||
val text = mEditorView.editor!!.text
|
||||
val text = mEditorView.editor.text
|
||||
if (text.length < 256 * 1024) {
|
||||
outState.putString("text", text)
|
||||
} else {
|
||||
@@ -228,7 +228,7 @@ open class EditActivity : BaseActivity(), DelegateHost, PermissionRequestProxyAc
|
||||
.observeOn(Schedulers.io())
|
||||
.map { PFiles.read(it) }
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({ mEditorView.editor!!.text = it }, Throwable::printStackTrace)
|
||||
.subscribe({ mEditorView.editor.text = it }, Throwable::printStackTrace)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -197,7 +197,7 @@ public class EditorMenu {
|
||||
}
|
||||
|
||||
private void startBuildApkActivity() {
|
||||
Uri uri = mEditorView.getUri();
|
||||
Uri uri = mEditorView.uri;
|
||||
if (uri != null) {
|
||||
BuildActivity.launch(mContext, uri.getPath());
|
||||
}
|
||||
@@ -217,12 +217,10 @@ public class EditorMenu {
|
||||
.title(R.string.text_pinch_to_zoom)
|
||||
.items(R.array.values_editor_pinch_to_zoom_strategy)
|
||||
.itemsCallbackSingleChoice(defSelectedIndex, (dialog, itemView, which, text) -> {
|
||||
if (mEditorView.editor != null) {
|
||||
String newKey = itemKeys.get(which);
|
||||
if (!Objects.equals(newKey, itemKey)) {
|
||||
Pref.putString(key, newKey);
|
||||
mEditorView.editor.notifyPinchToZoomStrategyChanged(newKey);
|
||||
}
|
||||
String newKey = itemKeys.get(which);
|
||||
if (!Objects.equals(newKey, itemKey)) {
|
||||
Pref.putString(key, newKey);
|
||||
mEditorView.editor.notifyPinchToZoomStrategyChanged(newKey);
|
||||
}
|
||||
return true;
|
||||
})
|
||||
|
||||
@@ -16,8 +16,8 @@ import android.util.AttributeSet
|
||||
import android.util.Log
|
||||
import android.util.SparseBooleanArray
|
||||
import android.view.View
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import androidx.core.view.GravityCompat
|
||||
import androidx.drawerlayout.widget.DrawerLayout
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
@@ -26,9 +26,6 @@ import com.google.android.material.snackbar.Snackbar
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import org.androidannotations.annotations.AfterViews
|
||||
import org.androidannotations.annotations.EViewGroup
|
||||
import org.androidannotations.annotations.ViewById
|
||||
import org.autojs.autojs.AutoJs
|
||||
import org.autojs.autojs.engine.JavaScriptEngine
|
||||
import org.autojs.autojs.engine.ScriptEngine
|
||||
@@ -77,6 +74,7 @@ import org.autojs.autojs.util.Observers
|
||||
import org.autojs.autojs.util.ViewUtils.showSnack
|
||||
import org.autojs.autojs.util.ViewUtils.showToast
|
||||
import org.autojs.autojs6.R
|
||||
import org.autojs.autojs6.databinding.EditorViewBinding
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
@@ -84,62 +82,49 @@ import java.io.File
|
||||
* Modified by SuperMonster003 as of May 1, 2023.
|
||||
* Transformed by SuperMonster003 on May 1, 2023.
|
||||
*/
|
||||
@SuppressLint("NonConstantResourceId")
|
||||
@EViewGroup(R.layout.editor_view)
|
||||
// FIXME by SuperMonster003 on May 13, 2023.
|
||||
// ! Failed many times to migrate this view with annotation to view binding.
|
||||
// ! And this is the last view with annotation in the whole project so far.
|
||||
// FIXME by SuperMonster003 on Oct 18, 2023.
|
||||
// ! Gradle property "android.nonFinalResIds"
|
||||
// ! can't be enabled (by default since Android Gradle Plugin version 8.0),
|
||||
// ! as final resource ID used in current class.
|
||||
open class EditorView : FrameLayout, OnHintClickListener, ClickCallback, ToolbarFragment.OnMenuItemClickListener {
|
||||
@SuppressLint("CheckResult")
|
||||
class EditorView : LinearLayout, OnHintClickListener, ClickCallback, ToolbarFragment.OnMenuItemClickListener {
|
||||
|
||||
private var binding: EditorViewBinding = EditorViewBinding.bind(View.inflate(context, R.layout.editor_view, this))
|
||||
|
||||
@JvmField
|
||||
@ViewById(R.id.editor)
|
||||
var editor: CodeEditor? = null
|
||||
val editor: CodeEditor = binding.editor
|
||||
|
||||
@JvmField
|
||||
@ViewById(R.id.debug_bar)
|
||||
var debugBar: DebugBar? = null
|
||||
val debugBar: DebugBar = binding.debugBar
|
||||
|
||||
@JvmField
|
||||
@ViewById(R.id.code_completion_bar)
|
||||
var mCodeCompletionBar: CodeCompletionBar? = null
|
||||
|
||||
@JvmField
|
||||
@ViewById(R.id.input_method_enhance_bar)
|
||||
var mInputMethodEnhanceBar: View? = null
|
||||
|
||||
@JvmField
|
||||
@ViewById(R.id.symbol_bar)
|
||||
var mSymbolBar: CodeCompletionBar? = null
|
||||
|
||||
@JvmField
|
||||
@ViewById(R.id.functions)
|
||||
var mShowFunctionsButton: ImageView? = null
|
||||
|
||||
@JvmField
|
||||
@ViewById(R.id.functions_keyboard)
|
||||
var mFunctionsKeyboard: FunctionsKeyboardView? = null
|
||||
|
||||
@JvmField
|
||||
@ViewById(R.id.docs)
|
||||
var mDocsWebView: EWebView? = null
|
||||
|
||||
@JvmField
|
||||
@ViewById(R.id.drawer_layout)
|
||||
var mDrawerLayout: DrawerLayout? = null
|
||||
|
||||
var name: String? = null
|
||||
private set
|
||||
|
||||
@JvmField
|
||||
var uri: Uri? = null
|
||||
private set
|
||||
|
||||
var scriptExecutionId = 0
|
||||
private set
|
||||
|
||||
val activity: FragmentActivity
|
||||
get() {
|
||||
var context = context
|
||||
while (context !is Activity && context is ContextWrapper) {
|
||||
context = context.baseContext
|
||||
}
|
||||
return context as FragmentActivity
|
||||
}
|
||||
|
||||
val isTextChanged: Boolean
|
||||
get() = editor.isTextChanged
|
||||
|
||||
private val scriptExecution: ScriptExecution?
|
||||
get() = AutoJs.instance.scriptEngineService.getScriptExecution(scriptExecutionId)
|
||||
|
||||
private val mCodeCompletionBar: CodeCompletionBar = binding.codeCompletionBar
|
||||
private val mInputMethodEnhanceBar: View = binding.inputMethodEnhanceBar
|
||||
private val mSymbolBar: CodeCompletionBar = binding.symbolBar
|
||||
private val mShowFunctionsButton: ImageView = binding.functions
|
||||
private val mFunctionsKeyboard: FunctionsKeyboardView = binding.functionsKeyboard
|
||||
private val mDocsWebView: EWebView = binding.docs
|
||||
private val mDrawerLayout: DrawerLayout = binding.drawerLayout
|
||||
|
||||
private var mReadOnly = false
|
||||
private var mAutoCompletion: AutoCompletion? = null
|
||||
private var mEditorTheme: Theme? = null
|
||||
@@ -156,7 +141,7 @@ open class EditorView : FrameLayout, OnHintClickListener, ClickCallback, Toolbar
|
||||
val line = intent.getIntExtra(EXTRA_EXCEPTION_LINE_NUMBER, -1)
|
||||
val col = intent.getIntExtra(EXTRA_EXCEPTION_COLUMN_NUMBER, 0)
|
||||
if (line >= 1) {
|
||||
editor!!.jumpTo(line - 1, col)
|
||||
editor.jumpTo(line - 1, col)
|
||||
}
|
||||
msg?.let { showErrorMessage(it) }
|
||||
}
|
||||
@@ -169,9 +154,26 @@ open class EditorView : FrameLayout, OnHintClickListener, ClickCallback, Toolbar
|
||||
private var mTmpSavedFileForRunning: File? = null
|
||||
|
||||
constructor(context: Context) : super(context)
|
||||
|
||||
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
|
||||
|
||||
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
|
||||
|
||||
init {
|
||||
setUpEditor()
|
||||
setUpInputMethodEnhancedBar()
|
||||
setUpFunctionsKeyboard()
|
||||
setMenuItemStatus(R.id.save, false)
|
||||
mDocsWebView.apply {
|
||||
webView.settings.displayZoomControls = true
|
||||
webView.loadUrl(getUrl("index.html"))
|
||||
}
|
||||
Themes.getCurrent(context)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe { theme: Theme? -> setTheme(theme) }
|
||||
initNormalToolbar()
|
||||
}
|
||||
|
||||
@SuppressLint("UnspecifiedRegisterReceiverFlag")
|
||||
override fun onAttachedToWindow() {
|
||||
super.onAttachedToWindow()
|
||||
@@ -203,14 +205,14 @@ open class EditorView : FrameLayout, OnHintClickListener, ClickCallback, Toolbar
|
||||
findViewById<View>(R.id.run).visibility = GONE
|
||||
}
|
||||
if (mReadOnly) {
|
||||
editor!!.setReadOnly(true)
|
||||
editor.setReadOnly(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun setRestoredText(text: String) {
|
||||
mRestoredText = text
|
||||
editor!!.text = text
|
||||
editor.text = text
|
||||
}
|
||||
|
||||
private fun handleText(intent: Intent): Observable<String> {
|
||||
@@ -241,11 +243,11 @@ open class EditorView : FrameLayout, OnHintClickListener, ClickCallback, Toolbar
|
||||
|
||||
private fun setInitialText(text: String) {
|
||||
if (mRestoredText != null) {
|
||||
editor!!.text = mRestoredText!!
|
||||
editor.text = mRestoredText!!
|
||||
mRestoredText = null
|
||||
return
|
||||
}
|
||||
editor!!.setInitialText(text)
|
||||
editor.setInitialText(text)
|
||||
}
|
||||
|
||||
private fun setMenuItemStatus(id: Int, enabled: Boolean) {
|
||||
@@ -263,23 +265,6 @@ open class EditorView : FrameLayout, OnHintClickListener, ClickCallback, Toolbar
|
||||
return mMenuItemStatus[id, defValue]
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
@AfterViews
|
||||
fun init() {
|
||||
setUpEditor()
|
||||
setUpInputMethodEnhancedBar()
|
||||
setUpFunctionsKeyboard()
|
||||
setMenuItemStatus(R.id.save, false)
|
||||
mDocsWebView?.apply {
|
||||
webView.settings.displayZoomControls = true
|
||||
webView.loadUrl(getUrl("index.html"))
|
||||
}
|
||||
Themes.getCurrent(context)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe { theme: Theme? -> setTheme(theme) }
|
||||
initNormalToolbar()
|
||||
}
|
||||
|
||||
private fun initNormalToolbar() {
|
||||
mNormalToolbar.apply {
|
||||
setOnMenuItemClickListener(this@EditorView)
|
||||
@@ -298,7 +283,7 @@ open class EditorView : FrameLayout, OnHintClickListener, ClickCallback, Toolbar
|
||||
.setFunctionsView(mFunctionsKeyboard)
|
||||
.setFunctionsTrigger(mShowFunctionsButton)
|
||||
|
||||
.setEditView(editor!!.codeEditText)
|
||||
.setEditView(editor.codeEditText)
|
||||
.build()
|
||||
|
||||
// @ArchivedTodo by 抠脚本人 on Jul 10, 2023.
|
||||
@@ -313,21 +298,21 @@ open class EditorView : FrameLayout, OnHintClickListener, ClickCallback, Toolbar
|
||||
// ! 此处的点击事件回调注册是为了使功能键盘智能提示的属性可以实现其接口对应的功能:
|
||||
// ! 点击: 自动补全, 并根据情况添加括号或句点符号等.
|
||||
// ! 长按: 以浮动窗口形式展示 [方法/属性/模块] 对应的文档内容 (如果存在的话).
|
||||
mFunctionsKeyboard!!.setClickCallback(this)
|
||||
mFunctionsKeyboard.setClickCallback(this)
|
||||
|
||||
mShowFunctionsButton!!.setOnLongClickListener {
|
||||
true.also { editor!!.beautifyCode() }
|
||||
mShowFunctionsButton.setOnLongClickListener {
|
||||
true.also { editor.beautifyCode() }
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpInputMethodEnhancedBar() {
|
||||
mSymbolBar!!.let { bar ->
|
||||
mSymbolBar.let { bar ->
|
||||
bar.setOnHintClickListener(this)
|
||||
bar.codeCompletions = Symbols.getSymbols()
|
||||
}
|
||||
mCodeCompletionBar!!.let { bar ->
|
||||
mCodeCompletionBar.let { bar ->
|
||||
bar.setOnHintClickListener(this)
|
||||
AutoCompletion(context, editor!!.codeEditText).apply {
|
||||
AutoCompletion(context, editor.codeEditText).apply {
|
||||
setAutoCompleteCallback { bar.codeCompletions = it }
|
||||
mAutoCompletion = this
|
||||
}
|
||||
@@ -335,14 +320,14 @@ open class EditorView : FrameLayout, OnHintClickListener, ClickCallback, Toolbar
|
||||
}
|
||||
|
||||
private fun setUpEditor() {
|
||||
editor!!.let { editor ->
|
||||
editor.let { editor ->
|
||||
editor.codeEditText.let { editText ->
|
||||
editText.addTextChangedListener(SimpleTextWatcher { _ ->
|
||||
setMenuItemStatus(R.id.save, editor.isTextChanged)
|
||||
setMenuItemStatus(R.id.undo, editor.canUndo())
|
||||
setMenuItemStatus(R.id.redo, editor.canRedo())
|
||||
})
|
||||
editText.textSize = getEditorTextSize(pxToSp(context, editText.textSize).toInt()).toFloat()
|
||||
editText.textSize = getEditorTextSize(pxToSp(editText.textSize).toInt()).toFloat()
|
||||
}
|
||||
editor.addCursorChangeCallback(object : CodeEditor.CursorChangeCallback {
|
||||
override fun onCursorChange(line: String, cursor: Int) {
|
||||
@@ -360,22 +345,22 @@ open class EditorView : FrameLayout, OnHintClickListener, ClickCallback, Toolbar
|
||||
private fun setTheme(theme: Theme?) {
|
||||
theme?.let {
|
||||
mEditorTheme = it
|
||||
editor!!.setTheme(it)
|
||||
mInputMethodEnhanceBar!!.setBackgroundColor(it.imeBarBackgroundColor)
|
||||
editor.setTheme(it)
|
||||
mInputMethodEnhanceBar.setBackgroundColor(it.imeBarBackgroundColor)
|
||||
val textColor = it.imeBarForegroundColor
|
||||
mCodeCompletionBar!!.setTextColor(textColor)
|
||||
mSymbolBar!!.setTextColor(textColor)
|
||||
mShowFunctionsButton!!.setColorFilter(textColor)
|
||||
mCodeCompletionBar.setTextColor(textColor)
|
||||
mSymbolBar.setTextColor(textColor)
|
||||
mShowFunctionsButton.setColorFilter(textColor)
|
||||
invalidate()
|
||||
}
|
||||
}
|
||||
|
||||
fun onBackPressed(): Boolean {
|
||||
if (mDrawerLayout!!.isDrawerOpen(GravityCompat.START)) {
|
||||
if (mDocsWebView!!.webView.canGoBack()) {
|
||||
mDocsWebView!!.webView.goBack()
|
||||
if (mDrawerLayout.isDrawerOpen(GravityCompat.START)) {
|
||||
if (mDocsWebView.webView.canGoBack()) {
|
||||
mDocsWebView.webView.goBack()
|
||||
} else {
|
||||
mDrawerLayout!!.closeDrawer(GravityCompat.START)
|
||||
mDrawerLayout.closeDrawer(GravityCompat.START)
|
||||
}
|
||||
return true
|
||||
}
|
||||
@@ -423,20 +408,20 @@ open class EditorView : FrameLayout, OnHintClickListener, ClickCallback, Toolbar
|
||||
return run(true, file, uri!!.path)
|
||||
}
|
||||
|
||||
private fun undo() = editor!!.undo()
|
||||
private fun undo() = editor.undo()
|
||||
|
||||
private fun redo() = editor!!.redo()
|
||||
private fun redo() = editor.redo()
|
||||
|
||||
fun save(): Observable<String> {
|
||||
val path = uri!!.path
|
||||
val backPath = "$path.save"
|
||||
move(path!!, backPath)
|
||||
return Observable.just(editor!!.text)
|
||||
return Observable.just(editor.text)
|
||||
.observeOn(Schedulers.io())
|
||||
.doOnNext { s: String? -> write(context.contentResolver.openOutputStream(uri!!)!!, s!!) }
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.doOnNext {
|
||||
editor!!.markTextAsSaved()
|
||||
editor.markTextAsSaved()
|
||||
setMenuItemStatus(R.id.save, false)
|
||||
}
|
||||
.doOnNext {
|
||||
@@ -451,13 +436,7 @@ open class EditorView : FrameLayout, OnHintClickListener, ClickCallback, Toolbar
|
||||
}
|
||||
|
||||
private fun doWithCurrentEngine(callback: Callback<ScriptEngine<*>>) {
|
||||
val execution = AutoJs.instance.scriptEngineService.getScriptExecution(scriptExecutionId)
|
||||
if (execution != null) {
|
||||
val engine = execution.engine
|
||||
if (engine != null) {
|
||||
callback.call(engine)
|
||||
}
|
||||
}
|
||||
scriptExecution?.engine?.let { callback.call(it) }
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
@@ -470,9 +449,9 @@ open class EditorView : FrameLayout, OnHintClickListener, ClickCallback, Toolbar
|
||||
}
|
||||
}
|
||||
|
||||
private fun findNext() = editor!!.findNext()
|
||||
private fun findNext() = editor.findNext()
|
||||
|
||||
private fun findPrev() = editor!!.findPrev()
|
||||
private fun findPrev() = editor.findPrev()
|
||||
|
||||
private fun cancelSearch() = showNormalToolbar()
|
||||
|
||||
@@ -482,22 +461,10 @@ open class EditorView : FrameLayout, OnHintClickListener, ClickCallback, Toolbar
|
||||
.commitAllowingStateLoss()
|
||||
}
|
||||
|
||||
val activity: FragmentActivity
|
||||
get() {
|
||||
var context = context
|
||||
while (context !is Activity && context is ContextWrapper) {
|
||||
context = context.baseContext
|
||||
}
|
||||
return context as FragmentActivity
|
||||
}
|
||||
|
||||
fun replace() {
|
||||
editor!!.replaceSelection()
|
||||
editor.replaceSelection()
|
||||
}
|
||||
|
||||
val isTextChanged: Boolean
|
||||
get() = editor!!.isTextChanged
|
||||
|
||||
fun showConsole() {
|
||||
doWithCurrentEngine { engine: ScriptEngine<*> -> (engine as JavaScriptEngine).runtime.console.show() }
|
||||
}
|
||||
@@ -509,32 +476,32 @@ open class EditorView : FrameLayout, OnHintClickListener, ClickCallback, Toolbar
|
||||
}
|
||||
|
||||
fun beautifyCode() {
|
||||
editor!!.beautifyCode()
|
||||
editor.beautifyCode()
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
fun selectEditorTheme() {
|
||||
editor!!.setProgress(true)
|
||||
editor.setProgress(true)
|
||||
Themes.getAllThemes(context)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe { themes: List<Theme?> ->
|
||||
editor!!.setProgress(false)
|
||||
editor.setProgress(false)
|
||||
selectEditorTheme(themes)
|
||||
}
|
||||
}
|
||||
|
||||
fun selectTextSize() {
|
||||
TextSizeSettingDialogBuilder(context)
|
||||
.initialValue(pxToSp(context, editor!!.codeEditText.textSize).toInt())
|
||||
.initialValue(pxToSp(editor.codeEditText.textSize).toInt())
|
||||
.callback { value: Int -> setTextSize(value) }
|
||||
.show()
|
||||
}
|
||||
|
||||
fun setTextSize(value: Int) {
|
||||
setEditorTextSize(value)
|
||||
editor!!.codeEditText.textSize = value.toFloat()
|
||||
editor!!.lastTextSize = value
|
||||
editor.codeEditText.textSize = value.toFloat()
|
||||
editor.lastTextSize = value
|
||||
}
|
||||
|
||||
private fun selectEditorTheme(themes: List<Theme?>) {
|
||||
@@ -557,7 +524,7 @@ open class EditorView : FrameLayout, OnHintClickListener, ClickCallback, Toolbar
|
||||
|
||||
@Throws(CheckedPatternSyntaxException::class)
|
||||
fun find(keywords: String, usingRegex: Boolean) {
|
||||
editor!!.find(keywords, usingRegex)
|
||||
editor.find(keywords, usingRegex)
|
||||
showSearchToolbar(false)
|
||||
}
|
||||
|
||||
@@ -572,21 +539,21 @@ open class EditorView : FrameLayout, OnHintClickListener, ClickCallback, Toolbar
|
||||
|
||||
@Throws(CheckedPatternSyntaxException::class)
|
||||
fun replace(keywords: String, replacement: String, usingRegex: Boolean) {
|
||||
editor!!.replace(keywords, replacement, usingRegex)
|
||||
editor.replace(keywords, replacement, usingRegex)
|
||||
showSearchToolbar(true)
|
||||
}
|
||||
|
||||
@Throws(CheckedPatternSyntaxException::class)
|
||||
fun replaceAll(keywords: String, replacement: String, usingRegex: Boolean) {
|
||||
editor!!.replaceAll(keywords, replacement, usingRegex)
|
||||
editor.replaceAll(keywords, replacement, usingRegex)
|
||||
}
|
||||
|
||||
fun debug() {
|
||||
activity.supportFragmentManager.beginTransaction()
|
||||
.replace(R.id.toolbar_menu, DebugToolbarFragment())
|
||||
.commit()
|
||||
debugBar!!.visibility = VISIBLE
|
||||
mInputMethodEnhanceBar!!.visibility = GONE
|
||||
debugBar.visibility = VISIBLE
|
||||
mInputMethodEnhanceBar.visibility = GONE
|
||||
mDebugging = true
|
||||
}
|
||||
|
||||
@@ -597,9 +564,9 @@ open class EditorView : FrameLayout, OnHintClickListener, ClickCallback, Toolbar
|
||||
fragment.detachDebugger()
|
||||
}
|
||||
showNormalToolbar()
|
||||
editor!!.setDebuggingLine(-1)
|
||||
debugBar!!.visibility = GONE
|
||||
mInputMethodEnhanceBar!!.visibility = VISIBLE
|
||||
editor.setDebuggingLine(-1)
|
||||
debugBar.visibility = GONE
|
||||
mInputMethodEnhanceBar.visibility = VISIBLE
|
||||
mDebugging = false
|
||||
}
|
||||
|
||||
@@ -627,7 +594,7 @@ open class EditorView : FrameLayout, OnHintClickListener, ClickCallback, Toolbar
|
||||
// editor!!.commentLine()
|
||||
// } else editor!!.insert(completion.insertText)
|
||||
|
||||
editor!!.insert(completion.insertText)
|
||||
editor.insert(completion.insertText)
|
||||
}
|
||||
|
||||
override fun onHintLongClick(completions: CodeCompletions, pos: Int) {
|
||||
@@ -653,7 +620,7 @@ open class EditorView : FrameLayout, OnHintClickListener, ClickCallback, Toolbar
|
||||
completions[pos].let {
|
||||
when {
|
||||
// @Inspired by 抠脚本人 (https://github.com/little-alei) on Jul 13, 2023.
|
||||
it.insertText == "/" -> editor!!.commentHelper.handle()
|
||||
it.insertText == "/" -> editor.commentHelper.handle()
|
||||
it.url != null -> showManual(it.url, it.hint)
|
||||
}
|
||||
}
|
||||
@@ -665,8 +632,8 @@ open class EditorView : FrameLayout, OnHintClickListener, ClickCallback, Toolbar
|
||||
.title(title)
|
||||
.url(absUrl)
|
||||
.pinToLeft {
|
||||
mDocsWebView!!.webView.loadUrl(absUrl)
|
||||
mDrawerLayout!!.openDrawer(GravityCompat.START)
|
||||
mDocsWebView.webView.loadUrl(absUrl)
|
||||
mDrawerLayout.openDrawer(GravityCompat.START)
|
||||
}
|
||||
.show()
|
||||
}
|
||||
@@ -681,12 +648,12 @@ open class EditorView : FrameLayout, OnHintClickListener, ClickCallback, Toolbar
|
||||
p = "$p()"
|
||||
}
|
||||
if (property.isGlobal) {
|
||||
editor!!.insert(p)
|
||||
editor.insert(p)
|
||||
} else {
|
||||
editor!!.insert(m.name + "." + p)
|
||||
editor.insert(m.name + "." + p)
|
||||
}
|
||||
if (!property.isVariable) {
|
||||
editor!!.moveCursor(-1)
|
||||
editor.moveCursor(-1)
|
||||
}
|
||||
mFunctionsKeyboardHelper!!.hideFunctionsLayout(true)
|
||||
}
|
||||
@@ -699,15 +666,9 @@ open class EditorView : FrameLayout, OnHintClickListener, ClickCallback, Toolbar
|
||||
}
|
||||
}
|
||||
|
||||
val scriptExecution: ScriptExecution?
|
||||
get() = AutoJs.instance.scriptEngineService.getScriptExecution(scriptExecutionId)
|
||||
|
||||
override fun onSaveInstanceState(): Parcelable? {
|
||||
val bundle = Bundle()
|
||||
val superData = super.onSaveInstanceState()
|
||||
bundle.putParcelable("super_data", superData)
|
||||
bundle.putInt("script_execution_id", scriptExecutionId)
|
||||
return bundle
|
||||
override fun onSaveInstanceState() = Bundle().apply {
|
||||
putParcelable("super_data", super.onSaveInstanceState())
|
||||
putInt("script_execution_id", scriptExecutionId)
|
||||
}
|
||||
|
||||
override fun onRestoreInstanceState(state: Parcelable) {
|
||||
@@ -721,17 +682,17 @@ open class EditorView : FrameLayout, OnHintClickListener, ClickCallback, Toolbar
|
||||
}
|
||||
|
||||
fun destroy() {
|
||||
editor!!.destroy()
|
||||
editor.destroy()
|
||||
mAutoCompletion?.shutdown()
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
private fun saveToTmpFile(): Observable<File> {
|
||||
return Observable.fromCallable {
|
||||
val tmp = TmpScriptFiles.create(context)
|
||||
write(tmp, editor!!.text)
|
||||
mTmpSavedFileForRunning = tmp
|
||||
tmp
|
||||
TmpScriptFiles.create(context).also {
|
||||
write(it, editor.text)
|
||||
mTmpSavedFileForRunning = it
|
||||
}
|
||||
}.observeOn(Schedulers.io())
|
||||
}
|
||||
|
||||
@@ -748,4 +709,5 @@ open class EditorView : FrameLayout, OnHintClickListener, ClickCallback, Toolbar
|
||||
const val EXTRA_SAVE_ENABLED = "saveEnabled"
|
||||
const val EXTRA_RUN_ENABLED = "runEnabled"
|
||||
}
|
||||
|
||||
}
|
||||
@@ -59,7 +59,7 @@ class CodeEditor : HVScrollView {
|
||||
|
||||
val codeEditText: CodeEditText = binding.codeEditText.also {
|
||||
it.addTextChangedListener(AutoIndent(it))
|
||||
lastTextSize = getEditorTextSize(pxToSp(it.context, it.textSize).toInt())
|
||||
lastTextSize = getEditorTextSize(pxToSp(it.textSize).toInt())
|
||||
}
|
||||
|
||||
val lineCount
|
||||
|
||||
@@ -1,301 +0,0 @@
|
||||
package org.autojs.autojs.ui.edit.toolbar;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import org.autojs.autojs.execution.ScriptExecution;
|
||||
import org.autojs.autojs.pio.PFiles;
|
||||
import org.autojs.autojs.rhino.debug.DebugCallback;
|
||||
import org.autojs.autojs.rhino.debug.Debugger;
|
||||
import org.autojs.autojs.rhino.debug.Dim;
|
||||
import org.autojs.autojs.runtime.exception.ScriptInterruptedException;
|
||||
import org.autojs.autojs.ui.edit.EditorView;
|
||||
import org.autojs.autojs.ui.edit.debug.CodeEvaluator;
|
||||
import org.autojs.autojs.ui.edit.debug.DebugBar;
|
||||
import org.autojs.autojs.ui.edit.debug.DebuggerSingleton;
|
||||
import org.autojs.autojs.ui.edit.debug.WatchingVariable;
|
||||
import org.autojs.autojs.ui.edit.editor.CodeEditor;
|
||||
import org.autojs.autojs.util.ViewUtils;
|
||||
import org.autojs.autojs6.R;
|
||||
import org.autojs.autojs6.databinding.FragmentDebugToolbarBinding;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class DebugToolbarFragment extends ToolbarFragment implements DebugCallback, CodeEditor.CursorChangeCallback, CodeEvaluator {
|
||||
|
||||
private static final String LOG_TAG = "DebugToolbarFragment";
|
||||
private EditorView mEditorView;
|
||||
private boolean mCursorChangeFromUser = true;
|
||||
private Debugger mDebugger;
|
||||
private Handler mHandler;
|
||||
private String mCurrentEditorSourceUrl;
|
||||
private String mInitialEditorSourceUrl;
|
||||
private String mInitialEditorSource;
|
||||
|
||||
private final RecyclerView.AdapterDataObserver mVariableChangeObserver = new RecyclerView.AdapterDataObserver() {
|
||||
@Override
|
||||
public void onItemRangeInserted(int positionStart, int itemCount) {
|
||||
updateWatchingVariables(positionStart, positionStart + itemCount);
|
||||
}
|
||||
};
|
||||
private final CodeEditor.BreakpointChangeListener mBreakpointChangeListener = new CodeEditor.BreakpointChangeListener() {
|
||||
@Override
|
||||
public void onBreakpointChange(int line, boolean enabled) {
|
||||
if (mDebugger != null) {
|
||||
mDebugger.breakpoint(line + 1, enabled);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAllBreakpointRemoved(int count) {
|
||||
mDebugger.clearAllBreakpoints();
|
||||
}
|
||||
};
|
||||
private FragmentDebugToolbarBinding binding;
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mHandler = new Handler();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
binding = FragmentDebugToolbarBinding.inflate(inflater, container, false);
|
||||
return binding.getRoot();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
mEditorView = findEditorView(view);
|
||||
mDebugger = DebuggerSingleton.get();
|
||||
mDebugger.setWeakDebugCallback(new WeakReference<>(this));
|
||||
setInterrupted(false);
|
||||
mCurrentEditorSourceUrl = mInitialEditorSourceUrl = mEditorView.getUri().toString();
|
||||
mInitialEditorSource = mEditorView.editor.getText();
|
||||
setupEditor();
|
||||
ScriptExecution execution = mEditorView.run(false);
|
||||
if (execution != null) {
|
||||
mDebugger.attach(execution);
|
||||
} else {
|
||||
mEditorView.exitDebugging();
|
||||
}
|
||||
|
||||
Log.d(LOG_TAG, "onViewCreated");
|
||||
|
||||
// @Caution by SuperMonster003 on May 13, 2023.
|
||||
// ! Do not place these listeners into onCreateView method.
|
||||
|
||||
binding.stepOver.setOnClickListener(v -> stepOver());
|
||||
binding.stepInto.setOnClickListener(v -> stepInto());
|
||||
binding.stepOut.setOnClickListener(v -> stepOut());
|
||||
binding.stopScript.setOnClickListener(v -> stopScript());
|
||||
binding.resumeScript.setOnClickListener(v -> resumeScript());
|
||||
}
|
||||
|
||||
private void setupEditor() {
|
||||
CodeEditor editor = mEditorView.editor;
|
||||
editor.setRedoUndoEnabled(false);
|
||||
editor.addCursorChangeCallback(this);
|
||||
editor.setBreakpointChangeListener(mBreakpointChangeListener);
|
||||
DebugBar debugBar = mEditorView.debugBar;
|
||||
debugBar.registerVariableChangeObserver(mVariableChangeObserver);
|
||||
debugBar.setCodeEvaluator(this);
|
||||
}
|
||||
|
||||
private void setInterrupted(boolean interrupted) {
|
||||
setMenuItemStatus(R.id.step_into, interrupted);
|
||||
setMenuItemStatus(R.id.step_over, interrupted);
|
||||
setMenuItemStatus(R.id.step_out, interrupted);
|
||||
setMenuItemStatus(R.id.resume_script, interrupted);
|
||||
if (!interrupted && mEditorView != null) {
|
||||
mEditorView.editor.setDebuggingLine(-1);
|
||||
}
|
||||
}
|
||||
|
||||
public void detachDebugger() {
|
||||
if (!mDebugger.isAttached()) {
|
||||
return;
|
||||
}
|
||||
Log.d(LOG_TAG, "detachDebugger");
|
||||
mDebugger.detach();
|
||||
if (mEditorView == null) {
|
||||
return;
|
||||
}
|
||||
CodeEditor editor = mEditorView.editor;
|
||||
if (!TextUtils.equals(mInitialEditorSourceUrl, mCurrentEditorSourceUrl)) {
|
||||
editor.setText(mInitialEditorSource);
|
||||
}
|
||||
editor.setRedoUndoEnabled(true);
|
||||
DebugBar debugBar = mEditorView.debugBar;
|
||||
debugBar.setTitle(null);
|
||||
debugBar.setCodeEvaluator(null);
|
||||
}
|
||||
|
||||
void stepOver() {
|
||||
setInterrupted(false);
|
||||
mDebugger.stepOver();
|
||||
}
|
||||
|
||||
void stepInto() {
|
||||
setInterrupted(false);
|
||||
mDebugger.stepInto();
|
||||
}
|
||||
|
||||
void stepOut() {
|
||||
setInterrupted(false);
|
||||
mDebugger.stepOut();
|
||||
}
|
||||
|
||||
void stopScript() {
|
||||
mEditorView.forceStop();
|
||||
}
|
||||
|
||||
void resumeScript() {
|
||||
setInterrupted(false);
|
||||
mDebugger.resume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSourceText(Dim.SourceInfo sourceInfo) {
|
||||
Log.d(LOG_TAG, "updateSourceText: url = " + sourceInfo.url());
|
||||
sourceInfo.removeAllBreakpoints();
|
||||
for (CodeEditor.Breakpoint breakpoint : mEditorView.editor.getBreakpoints().values()) {
|
||||
int line = breakpoint.line + 1;
|
||||
if (sourceInfo.breakableLine(line)) {
|
||||
sourceInfo.breakpoint(line, breakpoint.enabled);
|
||||
Log.d(LOG_TAG, "not breakable: " + line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterInterrupt(Dim.StackFrame stackFrame, String threadName, String message) {
|
||||
showDebuggingLineOnEditor(stackFrame, message);
|
||||
mHandler.post(this::updateWatchingVariables);
|
||||
}
|
||||
|
||||
private void updateWatchingVariables() {
|
||||
updateWatchingVariables(0, mEditorView.debugBar.getWatchingVariables().size());
|
||||
}
|
||||
|
||||
private void updateWatchingVariables(int start, int end) {
|
||||
if (!mDebugger.isAttached()) {
|
||||
return;
|
||||
}
|
||||
DebugBar debugBar = mEditorView.debugBar;
|
||||
List<WatchingVariable> variables = debugBar.getWatchingVariables();
|
||||
for (int i = start; i < end; i++) {
|
||||
WatchingVariable variable = variables.get(i);
|
||||
String value = eval(variable.getName());
|
||||
variable.setValue(value);
|
||||
}
|
||||
debugBar.refresh(start, end - start);
|
||||
}
|
||||
|
||||
public String eval(String expr) {
|
||||
return mDebugger.eval(expr);
|
||||
}
|
||||
|
||||
private void showDebuggingLineOnEditor(Dim.StackFrame stackFrame, String message) {
|
||||
//如果调试进入到其他脚本(例如模块脚本),则改变当前编辑器的文本为自动调试的脚本的代码
|
||||
String source;
|
||||
//标记是否需要更改编辑器文本
|
||||
boolean shouldChangeText = !stackFrame.getUrl().equals(mCurrentEditorSourceUrl);
|
||||
if (shouldChangeText) {
|
||||
source = stackFrame.sourceInfo().source();
|
||||
} else {
|
||||
source = null;
|
||||
}
|
||||
mCurrentEditorSourceUrl = stackFrame.getUrl();
|
||||
final int line = stackFrame.getLineNumber() - 1;
|
||||
mHandler.post(() -> {
|
||||
if (mEditorView == null) {
|
||||
return;
|
||||
}
|
||||
if (shouldChangeText) {
|
||||
mEditorView.editor.setText(source);
|
||||
}
|
||||
mCursorChangeFromUser = false;
|
||||
mEditorView.editor.setDebuggingLine(line);
|
||||
mEditorView.editor.jumpTo(line, 0);
|
||||
mEditorView.debugBar.setTitle(PFiles.getName(mCurrentEditorSourceUrl));
|
||||
setInterrupted(true);
|
||||
if (message != null && !message.equals(ScriptInterruptedException.class.getName())) {
|
||||
ViewUtils.showToast(mEditorView.getContext(), message, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onCursorChange(String line, int ch) {
|
||||
if (ch == 0 && !mCursorChangeFromUser) {
|
||||
mCursorChangeFromUser = true;
|
||||
return;
|
||||
}
|
||||
mCursorChangeFromUser = true;
|
||||
if (!mDebugger.isAttached()) {
|
||||
return;
|
||||
}
|
||||
String variable = findVariableOnCursor(line, ch);
|
||||
Log.d(LOG_TAG, "onCursorChange: variable = " + variable + ", ch = " + ch + ", line = " + line);
|
||||
String value = eval(variable);
|
||||
mEditorView.debugBar.updateCurrentVariable(variable, value);
|
||||
}
|
||||
|
||||
private String findVariableOnCursor(String line, int ch) {
|
||||
int end;
|
||||
for (end = ch; end < line.length(); end++) {
|
||||
if (!isIdentifierChar(line.charAt(end))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
int start;
|
||||
for (start = Math.min(ch - 1, line.length() - 1); start >= 0; start--) {
|
||||
if (!isIdentifierChar(line.charAt(start))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
start++;
|
||||
if (start < end && start < line.length() && start >= 0) {
|
||||
return line.substring(start, end);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isIdentifierChar(char c) {
|
||||
return Character.isDigit(c) || Character.isLetter(c) || c == '.' || c == '_';
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Integer> getMenuItemIds() {
|
||||
return Arrays.asList(R.id.step_over, R.id.step_into, R.id.step_out, R.id.resume_script, R.id.stop_script);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (mEditorView == null) {
|
||||
return;
|
||||
}
|
||||
CodeEditor editor = mEditorView.editor;
|
||||
editor.removeCursorChangeCallback(this);
|
||||
editor.setBreakpointChangeListener(null);
|
||||
DebugBar debugBar = mEditorView.debugBar;
|
||||
debugBar.unregisterVariableChangeObserver(mVariableChangeObserver);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,263 @@
|
||||
package org.autojs.autojs.ui.edit.toolbar
|
||||
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.text.TextUtils
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView.AdapterDataObserver
|
||||
import org.autojs.autojs.pio.PFiles.getName
|
||||
import org.autojs.autojs.rhino.debug.DebugCallback
|
||||
import org.autojs.autojs.rhino.debug.Debugger
|
||||
import org.autojs.autojs.rhino.debug.Dim
|
||||
import org.autojs.autojs.runtime.exception.ScriptInterruptedException
|
||||
import org.autojs.autojs.ui.edit.EditorView
|
||||
import org.autojs.autojs.ui.edit.debug.CodeEvaluator
|
||||
import org.autojs.autojs.ui.edit.debug.DebuggerSingleton
|
||||
import org.autojs.autojs.ui.edit.editor.CodeEditor.BreakpointChangeListener
|
||||
import org.autojs.autojs.ui.edit.editor.CodeEditor.CursorChangeCallback
|
||||
import org.autojs.autojs.util.ViewUtils.showToast
|
||||
import org.autojs.autojs6.R
|
||||
import org.autojs.autojs6.databinding.FragmentDebugToolbarBinding
|
||||
import java.lang.ref.WeakReference
|
||||
|
||||
/**
|
||||
* Transformed by SuperMonster003 on Oct 27, 2023.
|
||||
*/
|
||||
class DebugToolbarFragment : ToolbarFragment(), DebugCallback, CursorChangeCallback, CodeEvaluator {
|
||||
|
||||
private lateinit var binding: FragmentDebugToolbarBinding
|
||||
|
||||
private lateinit var mEditorView: EditorView
|
||||
private lateinit var mDebugger: Debugger
|
||||
private lateinit var mHandler: Handler
|
||||
private lateinit var mCurrentEditorSourceUrl: String
|
||||
private lateinit var mInitialEditorSourceUrl: String
|
||||
private lateinit var mInitialEditorSource: String
|
||||
|
||||
private var mCursorChangeFromUser = true
|
||||
|
||||
private val mVariableChangeObserver: AdapterDataObserver = object : AdapterDataObserver() {
|
||||
override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
|
||||
updateWatchingVariables(positionStart, positionStart + itemCount)
|
||||
}
|
||||
}
|
||||
|
||||
private val mBreakpointChangeListener: BreakpointChangeListener = object : BreakpointChangeListener {
|
||||
override fun onBreakpointChange(line: Int, enabled: Boolean) {
|
||||
mDebugger.breakpoint(line + 1, enabled)
|
||||
}
|
||||
|
||||
override fun onAllBreakpointRemoved(count: Int) {
|
||||
mDebugger.clearAllBreakpoints()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
mHandler = Handler(Looper.getMainLooper())
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||
return FragmentDebugToolbarBinding.inflate(inflater, container, false)
|
||||
.also { binding = it }.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
mEditorView = findEditorView(view)
|
||||
mDebugger = DebuggerSingleton.get()
|
||||
mDebugger.setWeakDebugCallback(WeakReference(this))
|
||||
setInterrupted(false)
|
||||
mInitialEditorSourceUrl = mEditorView.uri.toString()
|
||||
mCurrentEditorSourceUrl = mInitialEditorSourceUrl
|
||||
mInitialEditorSource = mEditorView.editor.text
|
||||
setupEditor()
|
||||
val execution = mEditorView.run(false)
|
||||
if (execution != null) {
|
||||
mDebugger.attach(execution)
|
||||
} else {
|
||||
mEditorView.exitDebugging()
|
||||
}
|
||||
Log.d(LOG_TAG, "onViewCreated")
|
||||
|
||||
// @Caution by SuperMonster003 on May 13, 2023.
|
||||
// ! Do not place these listeners into onCreateView method.
|
||||
binding.stepOver.setOnClickListener { stepOver() }
|
||||
binding.stepInto.setOnClickListener { stepInto() }
|
||||
binding.stepOut.setOnClickListener { stepOut() }
|
||||
binding.stopScript.setOnClickListener { stopScript() }
|
||||
binding.resumeScript.setOnClickListener { resumeScript() }
|
||||
}
|
||||
|
||||
private fun setupEditor() {
|
||||
mEditorView.editor.apply {
|
||||
setRedoUndoEnabled(false)
|
||||
addCursorChangeCallback(this@DebugToolbarFragment)
|
||||
setBreakpointChangeListener(mBreakpointChangeListener)
|
||||
}
|
||||
mEditorView.debugBar.apply {
|
||||
registerVariableChangeObserver(mVariableChangeObserver)
|
||||
setCodeEvaluator(this@DebugToolbarFragment)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setInterrupted(interrupted: Boolean) {
|
||||
setMenuItemStatus(R.id.step_into, interrupted)
|
||||
setMenuItemStatus(R.id.step_over, interrupted)
|
||||
setMenuItemStatus(R.id.step_out, interrupted)
|
||||
setMenuItemStatus(R.id.resume_script, interrupted)
|
||||
if (!interrupted) {
|
||||
mEditorView.editor.setDebuggingLine(-1)
|
||||
}
|
||||
}
|
||||
|
||||
fun detachDebugger() {
|
||||
if (!mDebugger.isAttached) {
|
||||
return
|
||||
}
|
||||
Log.d(LOG_TAG, "detachDebugger")
|
||||
mDebugger.detach()
|
||||
mEditorView.editor.also {
|
||||
if (!TextUtils.equals(mInitialEditorSourceUrl, mCurrentEditorSourceUrl)) {
|
||||
it.text = mInitialEditorSource
|
||||
}
|
||||
it.setRedoUndoEnabled(true)
|
||||
}
|
||||
mEditorView.debugBar.apply {
|
||||
setTitle(null)
|
||||
setCodeEvaluator(null)
|
||||
}
|
||||
}
|
||||
|
||||
private fun stepOver() = setInterrupted(false).also { mDebugger.stepOver() }
|
||||
|
||||
private fun stepInto() = setInterrupted(false).also { mDebugger.stepInto() }
|
||||
|
||||
private fun stepOut() = setInterrupted(false).also { mDebugger.stepOut() }
|
||||
|
||||
private fun stopScript() = mEditorView.forceStop()
|
||||
|
||||
private fun resumeScript() = setInterrupted(false).also { mDebugger.resume() }
|
||||
|
||||
override fun updateSourceText(sourceInfo: Dim.SourceInfo) {
|
||||
Log.d(LOG_TAG, "updateSourceText: url = " + sourceInfo.url())
|
||||
sourceInfo.removeAllBreakpoints()
|
||||
for (breakpoint in mEditorView.editor.breakpoints.values) {
|
||||
val line = breakpoint.line + 1
|
||||
if (sourceInfo.breakableLine(line)) {
|
||||
sourceInfo.breakpoint(line, breakpoint.enabled)
|
||||
Log.d(LOG_TAG, "not breakable: $line")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun enterInterrupt(stackFrame: Dim.StackFrame, threadName: String, message: String) {
|
||||
showDebuggingLineOnEditor(stackFrame, message)
|
||||
mHandler.post { updateWatchingVariables() }
|
||||
}
|
||||
|
||||
private fun updateWatchingVariables(start: Int = 0, end: Int = mEditorView.debugBar.watchingVariables.size) {
|
||||
if (!mDebugger.isAttached) {
|
||||
return
|
||||
}
|
||||
val debugBar = mEditorView.debugBar
|
||||
val variables = debugBar.watchingVariables
|
||||
for (i in start until end) {
|
||||
val variable = variables[i]
|
||||
variable.value = eval(variable.name)
|
||||
}
|
||||
debugBar.refresh(start, end - start)
|
||||
}
|
||||
|
||||
override fun eval(expr: String): String = mDebugger.eval(expr)
|
||||
|
||||
private fun showDebuggingLineOnEditor(stackFrame: Dim.StackFrame, message: String?) {
|
||||
// 标记是否需要更改编辑器文本
|
||||
val shouldChangeText = stackFrame.url != mCurrentEditorSourceUrl
|
||||
|
||||
// 如果调试进入到其他脚本 (例如模块脚本), 则改变当前编辑器的文本为自动调试的脚本的代码
|
||||
val source: String? = if (shouldChangeText) stackFrame.sourceInfo().source() else null
|
||||
|
||||
mCurrentEditorSourceUrl = stackFrame.url
|
||||
|
||||
val line = stackFrame.lineNumber - 1
|
||||
|
||||
mHandler.post {
|
||||
source?.let { mEditorView.editor.text = it }
|
||||
mCursorChangeFromUser = false
|
||||
mEditorView.editor.setDebuggingLine(line)
|
||||
mEditorView.editor.jumpTo(line, 0)
|
||||
mEditorView.debugBar.setTitle(getName(mCurrentEditorSourceUrl))
|
||||
setInterrupted(true)
|
||||
if (message != ScriptInterruptedException::class.java.name) {
|
||||
showToast(mEditorView.context, message, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCursorChange(line: String, cursor: Int) {
|
||||
if (cursor == 0 && !mCursorChangeFromUser) {
|
||||
mCursorChangeFromUser = true
|
||||
return
|
||||
}
|
||||
mCursorChangeFromUser = true
|
||||
if (!mDebugger.isAttached) {
|
||||
return
|
||||
}
|
||||
val variable = findVariableOnCursor(line, cursor)
|
||||
Log.d(LOG_TAG, "onCursorChange: variable = $variable, ch = $cursor, line = $line")
|
||||
variable?.let {
|
||||
eval(it)
|
||||
mEditorView.debugBar.updateCurrentVariable(variable, it)
|
||||
}
|
||||
}
|
||||
|
||||
private fun findVariableOnCursor(line: String, ch: Int): String? {
|
||||
var end = ch
|
||||
while (end < line.length) {
|
||||
if (!isIdentifierChar(line[end])) {
|
||||
break
|
||||
}
|
||||
end++
|
||||
}
|
||||
var start = (ch - 1).coerceAtMost(line.length - 1)
|
||||
while (start >= 0) {
|
||||
if (!isIdentifierChar(line[start])) {
|
||||
break
|
||||
}
|
||||
start--
|
||||
}
|
||||
start++
|
||||
return if (start < end && start < line.length && start >= 0) {
|
||||
line.substring(start, end)
|
||||
} else null
|
||||
}
|
||||
|
||||
private fun isIdentifierChar(c: Char): Boolean {
|
||||
return Character.isDigit(c) || Character.isLetter(c) || c == '.' || c == '_'
|
||||
}
|
||||
|
||||
override fun getMenuItemIds(): List<Int> {
|
||||
return listOf(R.id.step_over, R.id.step_into, R.id.step_out, R.id.resume_script, R.id.stop_script)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
mEditorView.editor.apply {
|
||||
removeCursorChangeCallback(this@DebugToolbarFragment)
|
||||
setBreakpointChangeListener(null)
|
||||
}
|
||||
mEditorView.debugBar.apply {
|
||||
unregisterVariableChangeObserver(mVariableChangeObserver)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val LOG_TAG = "DebugToolbarFragment"
|
||||
}
|
||||
|
||||
}
|
||||
@@ -123,7 +123,7 @@ class MainActivity : BaseActivity(), DelegateHost, HostActivity {
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
WrappedShizuku.checkShizukuPermission()
|
||||
WrappedShizuku.bindUserServiceIfNeeded()
|
||||
}
|
||||
|
||||
private fun recreateIfNeeded() {
|
||||
|
||||
@@ -2,7 +2,6 @@ package org.autojs.autojs.ui.main.drawer
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
@@ -18,6 +17,7 @@ import org.autojs.autojs.permission.DisplayOverOtherAppsPermission
|
||||
import org.autojs.autojs.permission.IgnoreBatteryOptimizationsPermission
|
||||
import org.autojs.autojs.permission.MediaProjectionPermission
|
||||
import org.autojs.autojs.permission.PostNotificationPermission
|
||||
import org.autojs.autojs.permission.ShizukuPermission
|
||||
import org.autojs.autojs.permission.UsageStatsPermission
|
||||
import org.autojs.autojs.permission.WriteSecureSettingsPermission
|
||||
import org.autojs.autojs.permission.WriteSystemSettingsPermission
|
||||
@@ -55,7 +55,6 @@ open class DrawerFragment : Fragment() {
|
||||
private lateinit var mDrawerMenu: RecyclerView
|
||||
private lateinit var mContext: Context
|
||||
private lateinit var mActivity: MainActivity
|
||||
// private lateinit var mReceiver: BatteryChangedReceiver
|
||||
|
||||
private lateinit var mAccessibilityServiceItem: DrawerMenuToggleableItem
|
||||
private lateinit var mForegroundServiceItem: DrawerMenuToggleableItem
|
||||
@@ -70,29 +69,21 @@ open class DrawerFragment : Fragment() {
|
||||
private lateinit var mWriteSystemSettingsItem: DrawerMenuToggleableItem
|
||||
private lateinit var mWriteSecuritySettingsItem: DrawerMenuToggleableItem
|
||||
private lateinit var mProjectMediaAccessItem: DrawerMenuToggleableItem
|
||||
private lateinit var mShizukuAccessItem: DrawerMenuToggleableItem
|
||||
private lateinit var mNightModeItem: DrawerMenuToggleableItem
|
||||
private lateinit var mAutoNightModeItem: DrawerMenuToggleableItem
|
||||
private lateinit var mKeepScreenOnWhenInForegroundItem: DrawerMenuToggleableItem
|
||||
private lateinit var mThemeColorItem: DrawerMenuShortcutItem
|
||||
private lateinit var mAboutAppAndDevItem: DrawerMenuShortcutItem
|
||||
|
||||
private val actionBatteryChangedIntentFilter = IntentFilter().apply {
|
||||
addAction("android.intent.action.ACTION_BATTERY_CHANGED")
|
||||
addAction("android.intent.action.ACTION_POWER_CONNECTED")
|
||||
addAction("android.intent.action.ACTION_POWER_DISCONNECTED")
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
EventBus.getDefault().register(this)
|
||||
// mReceiver = BatteryChangedReceiver()
|
||||
|
||||
mContext = requireContext()
|
||||
|
||||
mActivity = (requireActivity() as MainActivity).apply {
|
||||
// registerReceiver(mReceiver, actionBatteryChangedIntentFilter)
|
||||
}
|
||||
mActivity = (requireActivity() as MainActivity)
|
||||
|
||||
mAccessibilityServiceItem = DrawerMenuToggleableItem(
|
||||
AccessibilityService(mContext),
|
||||
@@ -224,6 +215,13 @@ open class DrawerFragment : Fragment() {
|
||||
R.string.text_project_media_access_description,
|
||||
)
|
||||
|
||||
mShizukuAccessItem = DrawerMenuToggleableItem(
|
||||
ShizukuPermission(mContext),
|
||||
R.drawable.ic_app_shizuku_representative,
|
||||
R.string.text_shizuku_access,
|
||||
R.string.text_shizuku_access_description,
|
||||
)
|
||||
|
||||
mAutoNightModeItem = DrawerMenuToggleableItem(
|
||||
object : DrawerMenuItemCustomHelper(mContext) {
|
||||
override fun toggle() {
|
||||
@@ -397,6 +395,7 @@ open class DrawerFragment : Fragment() {
|
||||
mWriteSystemSettingsItem,
|
||||
mWriteSecuritySettingsItem,
|
||||
mProjectMediaAccessItem,
|
||||
mShizukuAccessItem,
|
||||
DrawerMenuGroup(R.string.text_appearance),
|
||||
mAutoNightModeItem,
|
||||
mNightModeItem,
|
||||
@@ -432,6 +431,7 @@ open class DrawerFragment : Fragment() {
|
||||
mWriteSystemSettingsItem,
|
||||
mWriteSecuritySettingsItem,
|
||||
mProjectMediaAccessItem,
|
||||
mShizukuAccessItem,
|
||||
mKeepScreenOnWhenInForegroundItem,
|
||||
).forEach { it.sync() }
|
||||
|
||||
@@ -446,8 +446,6 @@ open class DrawerFragment : Fragment() {
|
||||
|
||||
companion object {
|
||||
|
||||
private val TAG = DrawerFragment::class.java.simpleName
|
||||
|
||||
lateinit var drawerMenuAdapter: DrawerMenuAdapter
|
||||
private set
|
||||
|
||||
@@ -458,27 +456,4 @@ open class DrawerFragment : Fragment() {
|
||||
|
||||
}
|
||||
|
||||
// class BatteryChangedReceiver : BroadcastReceiver() {
|
||||
//
|
||||
// override fun onReceive(context: Context, intent: Intent) {
|
||||
// val action = intent.action ?: return
|
||||
// when {
|
||||
// action.matches(Regex("android.intent.action.ACTION_(POWER_CONNECTED|BATTERY_CHANGED)", RegexOption.IGNORE_CASE)) -> {
|
||||
// Log.d(TAG, "Received broadcast: $action")
|
||||
//
|
||||
// // FIXME by SuperMonster003 on Jun 7, 2023.
|
||||
// // ! Code below doesn't work.
|
||||
//
|
||||
// // if (DeviceUtils.isPowerSourceUSB(context)) {
|
||||
// // Log.d(TAG, "Current power source is USB")
|
||||
// // drawerMenuAdapter.drawerMenuItems.find { it.title == R.string.text_server_mode }
|
||||
// // ?.takeUnless { it.isChecked }
|
||||
// // ?.let { it.subtitle = "true" }
|
||||
// // }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// }
|
||||
|
||||
}
|
||||
@@ -77,7 +77,6 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa
|
||||
private MaterialDialog mProgressDialog;
|
||||
private String mSource;
|
||||
private boolean mIsDefaultIcon = true;
|
||||
private boolean mIsApkTemplateInAssets = false;
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
@Override
|
||||
@@ -102,9 +101,7 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa
|
||||
binding.fab.setOnClickListener(v -> buildApk());
|
||||
binding.selectSource.setOnClickListener(v -> selectSourceFilePath());
|
||||
binding.selectOutput.setOnClickListener(v -> selectOutputDirPath());
|
||||
binding.selectTemplate.setOnClickListener(
|
||||
v -> selectTemplateFilePath()
|
||||
);
|
||||
binding.selectTemplate.setOnClickListener(v -> selectTemplateFilePath());
|
||||
mIcon.setOnClickListener(v -> selectIcon());
|
||||
|
||||
setToolbarAsBack(R.string.text_build_apk);
|
||||
@@ -112,9 +109,8 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa
|
||||
if (mSource != null) {
|
||||
setupWithSourceFile(new ScriptFile(mSource));
|
||||
}
|
||||
mIsApkTemplateInAssets = checkApkTemplateInAssets();
|
||||
if (mIsApkTemplateInAssets) {
|
||||
mTemplatePath.setText("file:///android_asset/template.apk");
|
||||
if (checkApkTemplateInAssets()) {
|
||||
mTemplatePath.setText(R.string.path_android_asset_template);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -319,7 +315,11 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa
|
||||
}
|
||||
|
||||
private ApkBuilder callApkBuilder(File tmpDir, File outApk, ApkBuilder.AppConfig appConfig) throws Exception {
|
||||
InputStream templateApk = mTemplatePath.getText() != null ? (mTemplatePath.getText().toString().equals("file:///android_asset/template.apk") ? getAssets().open("template.apk") : new java.io.FileInputStream(mTemplatePath.getText().toString())) : ApkBuilderPluginHelper.openTemplateApk(BuildActivity.this);
|
||||
InputStream templateApk = mTemplatePath.getText() != null
|
||||
? mTemplatePath.getText().toString().equals(getString(R.string.path_android_asset_template))
|
||||
? getAssets().open(TEMPLATE_APK_PATH)
|
||||
: new java.io.FileInputStream(mTemplatePath.getText().toString())
|
||||
: ApkBuilderPluginHelper.openTemplateApk(BuildActivity.this);
|
||||
return new ApkBuilder(templateApk, outApk, tmpDir.getPath())
|
||||
.setProgressCallback(BuildActivity.this)
|
||||
.prepare()
|
||||
|
||||
@@ -1,36 +1,56 @@
|
||||
package org.autojs.autojs.util
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.util.DisplayMetrics
|
||||
import android.util.DisplayMetrics.DENSITY_DEFAULT
|
||||
import android.util.TypedValue
|
||||
import android.util.TypedValue.COMPLEX_UNIT_DIP
|
||||
import android.util.TypedValue.COMPLEX_UNIT_SP
|
||||
import org.autojs.autojs.app.GlobalAppContext
|
||||
import org.autojs.autojs.runtime.api.ScreenMetrics
|
||||
import kotlin.math.ceil
|
||||
import kotlin.math.floor
|
||||
import kotlin.math.round
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
@Suppress("unused")
|
||||
object DisplayUtils {
|
||||
|
||||
@JvmStatic
|
||||
val displayMetrics: DisplayMetrics
|
||||
get() = ScreenMetrics.resources?.displayMetrics ?: GlobalAppContext.get().resources.displayMetrics
|
||||
|
||||
/**
|
||||
* This method converts dp unit to equivalent pixels, depending on device density.
|
||||
*
|
||||
* @param ctx Context to get resources and device specific display metrics
|
||||
* @param dp A value in dp (density independent pixels) unit. Which we need to convert into pixels
|
||||
* @return A float value to represent px equivalent to dp depending on device density
|
||||
*/
|
||||
@JvmStatic
|
||||
fun dpToPx(ctx: Context, dp: Float) = dp * (ctx.resources.displayMetrics.densityDpi.toFloat() / DENSITY_DEFAULT)
|
||||
fun dpToPx(dp: Float) = TypedValue.applyDimension(COMPLEX_UNIT_DIP, dp, displayMetrics)
|
||||
|
||||
/**
|
||||
* This method converts device specific pixels to density independent pixels.
|
||||
*
|
||||
* @param ctx Context to get resources and device specific display metrics
|
||||
* @param px A value in px (pixels) unit. Which we need to convert into db
|
||||
* @return A float value to represent dp equivalent to px value
|
||||
*/
|
||||
@JvmStatic
|
||||
fun pxToDp(ctx: Context, px: Float) = px / (ctx.resources.displayMetrics.densityDpi.toFloat() / DENSITY_DEFAULT)
|
||||
fun pxToDp(px: Float): Float {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
|
||||
return TypedValue.deriveDimension(COMPLEX_UNIT_DIP, px, displayMetrics)
|
||||
}
|
||||
return px / (displayMetrics.densityDpi.toFloat() / DENSITY_DEFAULT)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun pxToSp(ctx: Context, px: Float) = px / ctx.resources.displayMetrics.scaledDensity
|
||||
fun pxToSp(px: Float): Float {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
|
||||
return TypedValue.deriveDimension(COMPLEX_UNIT_SP, px, displayMetrics)
|
||||
}
|
||||
@Suppress("DEPRECATION")
|
||||
return px / displayMetrics.scaledDensity
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
@JvmStatic
|
||||
|
||||
Reference in New Issue
Block a user