Add floating console support
This commit is contained in:
@@ -2,24 +2,21 @@ package com.stardust.scriptdroid.autojs;
|
||||
|
||||
import android.accessibilityservice.AccessibilityService;
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.flurry.android.FlurryAgent;
|
||||
import com.stardust.autojs.ScriptEngineService;
|
||||
import com.stardust.autojs.ScriptEngineServiceBuilder;
|
||||
import com.stardust.autojs.ScriptExecutionListener;
|
||||
import com.stardust.autojs.engine.JavaScriptEngine;
|
||||
import com.stardust.autojs.engine.NodeJsJavaScriptEngineManager;
|
||||
import com.stardust.autojs.runtime.*;
|
||||
import com.stardust.autojs.script.ScriptSource;
|
||||
import com.stardust.automator.AccessibilityEventCommandHost;
|
||||
import com.stardust.automator.simple_action.SimpleActionPerformHost;
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.Pref;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.scripts.StorageScriptProvider;
|
||||
import com.stardust.scriptdroid.ui.console.StardustConsole;
|
||||
import com.stardust.util.Supplier;
|
||||
import com.stardust.util.UiHandler;
|
||||
import com.stardust.view.accessibility.AccessibilityInfoProvider;
|
||||
import com.stardust.scriptdroid.layout_inspector.LayoutInspector;
|
||||
import com.stardust.scriptdroid.record.accessibility.AccessibilityActionRecorder;
|
||||
@@ -51,54 +48,32 @@ public class AutoJs implements AccessibilityBridge {
|
||||
private final LayoutInspector mLayoutInspector = new LayoutInspector();
|
||||
private final ScriptEngineService mScriptEngineService;
|
||||
private final AccessibilityInfoProvider mAccessibilityInfoProvider;
|
||||
private final Handler mUiHandler;
|
||||
private final UiHandler mUiHandler;
|
||||
|
||||
|
||||
private AutoJs(final Context context) {
|
||||
mUiHandler = new Handler(context.getMainLooper());
|
||||
mUiHandler = new UiHandler(context);
|
||||
mAccessibilityInfoProvider = new AccessibilityInfoProvider(context.getPackageManager());
|
||||
NodeJsJavaScriptEngineManager manager = new NodeJsJavaScriptEngineManager(context);
|
||||
manager.setRequirePath(StorageScriptProvider.DEFAULT_DIRECTORY_PATH);
|
||||
mScriptEngineService = new ScriptEngineServiceBuilder()
|
||||
.context(context)
|
||||
.uiHandler(mUiHandler)
|
||||
.globalConsole(new TimberConsole())
|
||||
.engineManger(manager)
|
||||
.runtime(new Supplier<ScriptRuntime>() {
|
||||
|
||||
@Override
|
||||
public ScriptRuntime get() {
|
||||
return new ScriptRuntime(context, mUiHandler, new TimberConsole(), AutoJs.this);
|
||||
return new ScriptRuntime(mUiHandler, new StardustConsole(mUiHandler), AutoJs.this);
|
||||
}
|
||||
})
|
||||
.build();
|
||||
addAccessibilityServiceDelegates();
|
||||
setDefaultScriptExecutionListener(mScriptEngineService);
|
||||
}
|
||||
|
||||
|
||||
private static void setDefaultScriptExecutionListener(ScriptEngineService scriptEngineService) {
|
||||
final ScriptExecutionListener listener = scriptEngineService.getDefaultScriptExecutionListener();
|
||||
scriptEngineService.setDefaultScriptExecutionListener(new ScriptExecutionListener() {
|
||||
@Override
|
||||
public void onStart(JavaScriptEngine engine, ScriptSource source) {
|
||||
listener.onStart(engine, source);
|
||||
FlurryAgent.logEvent("EXEC:" + source.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(JavaScriptEngine engine, ScriptSource source, Object result) {
|
||||
listener.onSuccess(engine, source, result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onException(JavaScriptEngine engine, ScriptSource source, Exception e) {
|
||||
listener.onException(engine, source, e);
|
||||
}
|
||||
});
|
||||
mScriptEngineService.registerGlobalScriptExecutionListener(new ScriptExecutionGlobalListener());
|
||||
}
|
||||
|
||||
private void addAccessibilityServiceDelegates() {
|
||||
AccessibilityWatchDogService.addDelegate(100, mAccessibilityInfoProvider);
|
||||
// AccessibilityWatchDogService.addDelegate(200, mLayoutInspector);
|
||||
AccessibilityWatchDogService.addDelegate(300, mAccessibilityActionRecorder);
|
||||
// AccessibilityWatchDogService.addDelegate(400, mSimpleActionPerformHost);
|
||||
//AccessibilityWatchDogService.addDelegate(500, mAccessibilityEventCommandHost);
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.stardust.scriptdroid.autojs;
|
||||
|
||||
import com.flurry.android.FlurryAgent;
|
||||
import com.stardust.autojs.ScriptEngineService;
|
||||
import com.stardust.autojs.execution.ScriptExecution;
|
||||
import com.stardust.autojs.execution.ScriptExecutionListener;
|
||||
import com.stardust.autojs.runtime.ScriptInterruptedException;
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.R;
|
||||
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/5/3.
|
||||
*/
|
||||
|
||||
public class ScriptExecutionGlobalListener implements ScriptExecutionListener {
|
||||
private static final String ENGINE_TAG_START_TIME = "com.stardust.scriptdroid.autojs.Goodbye, World";
|
||||
|
||||
@Override
|
||||
public void onStart(ScriptExecution execution) {
|
||||
execution.getEngine().setTag(ENGINE_TAG_START_TIME, System.currentTimeMillis());
|
||||
FlurryAgent.logEvent("EXEC:" + execution.getSource().toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(ScriptExecution execution, Object result) {
|
||||
onFinish(execution);
|
||||
}
|
||||
|
||||
private void onFinish(ScriptExecution execution) {
|
||||
long millis = System.currentTimeMillis() - (long) execution.getEngine().getTag(ENGINE_TAG_START_TIME);
|
||||
execution.getRuntime().console.verbose(App.getApp().getString(R.string.text_execution_finished), execution.getSource().toString(), (double) millis / 1000);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onException(ScriptExecution execution, Exception e) {
|
||||
onFinish(execution);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
package com.stardust.scriptdroid.external.floating_window.console;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.view.ContextThemeWrapper;
|
||||
import android.view.View;
|
||||
|
||||
import com.stardust.enhancedfloaty.ResizableExpandableFloaty;
|
||||
import com.stardust.enhancedfloaty.ResizableExpandableFloatyService;
|
||||
import com.stardust.enhancedfloaty.ResizableFloaty;
|
||||
import com.stardust.enhancedfloaty.ResizableFloatyService;
|
||||
|
||||
import com.stardust.scriptdroid.R;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/4/20.
|
||||
*/
|
||||
|
||||
public class ConsoleFloaty extends ResizableExpandableFloaty {
|
||||
|
||||
private ContextWrapper mContextWrapper;
|
||||
private View mResizer, mMoveCursor;
|
||||
|
||||
public ConsoleFloaty() {
|
||||
setShouldRequestFocusWhenExpand(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View inflateCollapsedView(ResizableExpandableFloatyService service) {
|
||||
ensureContextWrapper(service);
|
||||
return View.inflate(mContextWrapper, R.layout.floating_window_collapse, null);
|
||||
}
|
||||
|
||||
private void ensureContextWrapper(Context context) {
|
||||
if (mContextWrapper == null) {
|
||||
mContextWrapper = new ContextThemeWrapper(context, R.style.AppTheme);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public View inflateExpandedView(ResizableExpandableFloatyService service) {
|
||||
ensureContextWrapper(service);
|
||||
View view = View.inflate(mContextWrapper, R.layout.floating_console_expand, null);
|
||||
setListeners(view, service);
|
||||
return view;
|
||||
}
|
||||
|
||||
private void setListeners(final View view, final ResizableExpandableFloatyService service) {
|
||||
view.findViewById(R.id.close).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
service.stopSelf();
|
||||
}
|
||||
});
|
||||
view.findViewById(R.id.move_or_resize).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (mMoveCursor.getVisibility() == View.VISIBLE) {
|
||||
mMoveCursor.setVisibility(View.GONE);
|
||||
mResizer.setVisibility(View.GONE);
|
||||
} else {
|
||||
mMoveCursor.setVisibility(View.VISIBLE);
|
||||
mResizer.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View getResizerView(View expandedView) {
|
||||
mResizer = expandedView.findViewById(R.id.resizer);
|
||||
return mResizer;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View getMoveCursorView(View expandedView) {
|
||||
mMoveCursor = expandedView.findViewById(R.id.move_cursor);
|
||||
return mMoveCursor;
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package com.stardust.scriptdroid.external.floating_window.console;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.stardust.enhancedfloaty.ResizableExpandableFloatyService;
|
||||
import com.stardust.enhancedfloaty.ResizableFloatyService;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/4/18.
|
||||
*/
|
||||
|
||||
public class FloatingConsole {
|
||||
|
||||
public static void startFloatingService(Context context) {
|
||||
ResizableExpandableFloatyService.startService(context, new ConsoleFloaty());
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
package com.stardust.scriptdroid.external.floating_window.console;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/4/30.
|
||||
*/
|
||||
|
||||
public class FloatingConsoleService {
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
package com.stardust.scriptdroid.external.floating_window.console;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.jraska.console.Console;
|
||||
import com.stardust.scriptdroid.R;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/4/30.
|
||||
*/
|
||||
|
||||
public class FloatingConsoleView extends Console {
|
||||
public FloatingConsoleView(Context context) {
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
public FloatingConsoleView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
public FloatingConsoleView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init();
|
||||
}
|
||||
|
||||
public FloatingConsoleView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
findViewById(R.id.console_scroll_view).setBackground(getBackground());
|
||||
((TextView) findViewById(R.id.console_text)).setTextIsSelectable(true);
|
||||
}
|
||||
}
|
||||
@@ -181,6 +181,8 @@ public class HoverMenuService extends Service {
|
||||
if (eventBus.isRegistered(this))
|
||||
eventBus.unregister(this);
|
||||
setIsRunning(false);
|
||||
mWindowViewController.removeView(mFloatingLayoutBoundsView);
|
||||
mWindowViewController.removeView(mFloatingLayoutHierarchyView);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
|
||||
import com.stardust.scriptdroid.service.AccessibilityWatchDogService;
|
||||
import com.stardust.util.UnderuseExecutors;
|
||||
import com.stardust.view.accessibility.AccessibilityDelegate;
|
||||
|
||||
import java.util.Set;
|
||||
@@ -20,7 +21,7 @@ public class LayoutInspector {
|
||||
|
||||
private volatile NodeInfo mCapture;
|
||||
private volatile boolean mDumping = false;
|
||||
private Executor mExecutor = Executors.newSingleThreadExecutor();
|
||||
private Executor mExecutor = UnderuseExecutors.getExecutor();
|
||||
|
||||
public void captureCurrentWindow() {
|
||||
AccessibilityService service = AccessibilityWatchDogService.getInstance();
|
||||
|
||||
@@ -3,26 +3,18 @@ package com.stardust.scriptdroid.service;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
|
||||
import com.stardust.autojs.runtime.JavascriptInterface;
|
||||
import com.stardust.view.accessibility.AccessibilityDelegate;
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.tool.AccessibilityServiceTool;
|
||||
import com.stardust.view.accessibility.AccessibilityDelegate;
|
||||
import com.stardust.view.accessibility.AccessibilityService;
|
||||
import com.stardust.view.accessibility.AccessibilityServiceUtils;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/2/14.
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
package com.stardust.scriptdroid.ui.console;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.view.ContextThemeWrapper;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.stardust.enhancedfloaty.FloatyService;
|
||||
import com.stardust.enhancedfloaty.ResizableExpandableFloaty;
|
||||
import com.stardust.enhancedfloaty.ResizableExpandableFloatyWindow;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.util.ViewUtil;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/4/20.
|
||||
*/
|
||||
|
||||
public class ConsoleFloaty extends ResizableExpandableFloaty.AbstractResizableExpandableFloaty {
|
||||
|
||||
private ContextWrapper mContextWrapper;
|
||||
private View mResizer, mMoveCursor;
|
||||
private TextView mTitleView;
|
||||
private StardustConsole mConsole;
|
||||
private CharSequence mTitle;
|
||||
|
||||
public ConsoleFloaty(StardustConsole console) {
|
||||
mConsole = console;
|
||||
setShouldRequestFocusWhenExpand(false);
|
||||
setInitialX(100);
|
||||
setInitialY(1000);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View inflateCollapsedView(FloatyService service, final ResizableExpandableFloatyWindow window) {
|
||||
ensureContextWrapper(service);
|
||||
View view = View.inflate(mContextWrapper, R.layout.floating_window_collapse, null);
|
||||
view.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
window.expand();
|
||||
}
|
||||
});
|
||||
return view;
|
||||
}
|
||||
|
||||
private void ensureContextWrapper(Context context) {
|
||||
if (mContextWrapper == null) {
|
||||
mContextWrapper = new ContextThemeWrapper(context, R.style.AppTheme);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public View inflateExpandedView(FloatyService service, ResizableExpandableFloatyWindow window) {
|
||||
ensureContextWrapper(service);
|
||||
View view = View.inflate(mContextWrapper, R.layout.floating_console_expand, null);
|
||||
((ConsoleView) view.findViewById(R.id.console)).setConsole(mConsole);
|
||||
setListeners(view, window);
|
||||
initConsoleTitle(view);
|
||||
setInitialMeasure(view);
|
||||
return view;
|
||||
}
|
||||
|
||||
private void setInitialMeasure(final View view) {
|
||||
view.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ViewUtil.setViewMeasure(view, 800, 800);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void initConsoleTitle(View view) {
|
||||
mTitleView = (TextView) view.findViewById(R.id.title);
|
||||
if (mTitle != null) {
|
||||
mTitleView.setText(mTitle);
|
||||
}
|
||||
}
|
||||
|
||||
private void setListeners(final View view, final ResizableExpandableFloatyWindow window) {
|
||||
view.findViewById(R.id.close).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
window.close();
|
||||
}
|
||||
});
|
||||
view.findViewById(R.id.move_or_resize).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (mMoveCursor.getVisibility() == View.VISIBLE) {
|
||||
mMoveCursor.setVisibility(View.GONE);
|
||||
mResizer.setVisibility(View.GONE);
|
||||
} else {
|
||||
mMoveCursor.setVisibility(View.VISIBLE);
|
||||
mResizer.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
});
|
||||
view.findViewById(R.id.minimize).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
window.collapse();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View getResizerView(View expandedView) {
|
||||
mResizer = expandedView.findViewById(R.id.resizer);
|
||||
return mResizer;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View getMoveCursorView(View expandedView) {
|
||||
mMoveCursor = expandedView.findViewById(R.id.move_cursor);
|
||||
return mMoveCursor;
|
||||
}
|
||||
|
||||
public void setTitle(final CharSequence title) {
|
||||
mTitle = title;
|
||||
if (mTitleView != null) {
|
||||
mTitleView.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mTitleView.setText(title);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
package com.stardust.scriptdroid.ui.console;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.IntDef;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.widget.AppCompatTextView;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.Spanned;
|
||||
import android.text.method.ScrollingMovementMethod;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.util.MapEntries;
|
||||
import com.stardust.util.SparseArrayEntries;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/5/2.
|
||||
*/
|
||||
|
||||
public class ConsoleView extends LinearLayout implements StardustConsole.LogListener {
|
||||
|
||||
private static final SparseArray<Integer> COLORS = new SparseArrayEntries<Integer>()
|
||||
.entry(Log.VERBOSE, 0xdfc0c0c0)
|
||||
.entry(Log.DEBUG, 0xdfffffff)
|
||||
.entry(Log.INFO, 0xff64dd17)
|
||||
.entry(Log.WARN, 0xff2962ff)
|
||||
.entry(Log.ERROR, 0xffd50000)
|
||||
.entry(Log.ASSERT, 0xffff534e)
|
||||
.sparseArray();
|
||||
|
||||
private StardustConsole mConsole;
|
||||
private TextView mTextView;
|
||||
private EditText mEditText;
|
||||
|
||||
public ConsoleView(Context context) {
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
public ConsoleView(Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
public ConsoleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
inflate(getContext(), R.layout.console_view, this);
|
||||
mTextView = (TextView) findViewById(R.id.textView);
|
||||
}
|
||||
|
||||
private void initEditText() {
|
||||
//mEditText = (EditText) findViewById(R.id.ediText);
|
||||
mEditText.setFocusableInTouchMode(true);
|
||||
mTextView.setMovementMethod(new ScrollingMovementMethod());
|
||||
setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
mEditText.requestFocus();
|
||||
InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setConsole(StardustConsole console) {
|
||||
mConsole = console;
|
||||
mConsole.setLogListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewLog(StardustConsole.Log log) {
|
||||
log(log.level, log.content);
|
||||
log(log.level, "\n");
|
||||
}
|
||||
|
||||
private void log(int level, CharSequence log) {
|
||||
int color = getColorForLevel(level);
|
||||
final Spannable spannable = buildColorSpannable(log, color);
|
||||
post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mTextView.append(spannable);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
private void scrollToBottom() {
|
||||
mTextView.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mTextView.scrollTo(0, mTextView.getLayout().getLineTop(mTextView.getLineCount()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private Spannable buildColorSpannable(CharSequence log, int color) {
|
||||
Spannable spannable = new SpannableString(log);
|
||||
spannable.setSpan(new ForegroundColorSpan(color), 0, log.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
|
||||
return spannable;
|
||||
}
|
||||
|
||||
private int getColorForLevel(int level) {
|
||||
return COLORS.get(level);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLogClear() {
|
||||
mTextView.setText("");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onWindowVisibilityChanged(int visibility) {
|
||||
super.onWindowVisibilityChanged(visibility);
|
||||
if (visibility == VISIBLE) {
|
||||
refreshLog();
|
||||
}
|
||||
}
|
||||
|
||||
private void refreshLog() {
|
||||
if (mConsole != null) {
|
||||
mTextView.setText("");
|
||||
for (StardustConsole.Log log : mConsole.getLogs()) {
|
||||
onNewLog(log);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
package com.stardust.scriptdroid.ui.console;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import com.stardust.autojs.runtime.AbstractConsole;
|
||||
import com.stardust.autojs.runtime.api.Console;
|
||||
import com.stardust.enhancedfloaty.FloatyService;
|
||||
import com.stardust.enhancedfloaty.ResizableExpandableFloatyWindow;
|
||||
import com.stardust.scriptdroid.autojs.AutoJs;
|
||||
import com.stardust.util.UiHandler;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/5/2.
|
||||
*/
|
||||
|
||||
public class StardustConsole extends AbstractConsole {
|
||||
|
||||
public static class Log {
|
||||
|
||||
public int level;
|
||||
public CharSequence content;
|
||||
|
||||
public Log(int level, CharSequence content) {
|
||||
this.level = level;
|
||||
this.content = content;
|
||||
}
|
||||
}
|
||||
|
||||
public interface LogListener {
|
||||
void onNewLog(Log log);
|
||||
|
||||
void onLogClear();
|
||||
}
|
||||
|
||||
private final Console GLOBAL_CONSOLE = AutoJs.getInstance().getScriptEngineService().getGlobalConsole();
|
||||
private List<Log> mLogs = new ArrayList<>();
|
||||
private ResizableExpandableFloatyWindow mFloatyWindow;
|
||||
private ConsoleFloaty mConsoleFloaty;
|
||||
private LogListener mLogListener;
|
||||
private UiHandler mUiHandler;
|
||||
|
||||
public StardustConsole(UiHandler uiHandler) {
|
||||
mUiHandler = uiHandler;
|
||||
mConsoleFloaty = new ConsoleFloaty(this);
|
||||
mFloatyWindow = new ResizableExpandableFloatyWindow(mConsoleFloaty);
|
||||
}
|
||||
|
||||
public void setLogListener(LogListener logListener) {
|
||||
mLogListener = logListener;
|
||||
}
|
||||
|
||||
public List<Log> getLogs() {
|
||||
return mLogs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void println(int level, CharSequence charSequence) {
|
||||
Log log = new Log(level, charSequence);
|
||||
mLogs.add(log);
|
||||
GLOBAL_CONSOLE.println(level, charSequence);
|
||||
if (mLogListener != null) {
|
||||
mLogListener.onNewLog(log);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
mLogs.clear();
|
||||
if (mLogListener != null) {
|
||||
mLogListener.onLogClear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
startFloatyService();
|
||||
mUiHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
FloatyService.addWindow(mFloatyWindow);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void startFloatyService() {
|
||||
Context context = mUiHandler.getContext();
|
||||
context.startService(new Intent(context, FloatyService.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hide() {
|
||||
try {
|
||||
mFloatyWindow.close();
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTitle(CharSequence title) {
|
||||
mConsoleFloaty.setTitle(title);
|
||||
}
|
||||
}
|
||||
@@ -26,16 +26,16 @@ public class TimberConsole extends AbstractConsole {
|
||||
Timber.plant(new ConsoleTree.Builder()
|
||||
.minPriority(Log.VERBOSE)
|
||||
.verboseColor(0xff909090)
|
||||
.debugColor(0xffc88b48)
|
||||
.infoColor(0xffc9c9c9)
|
||||
.warnColor(0xffa97db6)
|
||||
.debugColor(0xdf000000)
|
||||
.infoColor(0xdf4caf50)
|
||||
.warnColor(0xff2196f3)
|
||||
.errorColor(0xffff534e)
|
||||
.assertColor(0xffff5540)
|
||||
.assertColor(0xffff534e)
|
||||
.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void log(int level, CharSequence charSequence) {
|
||||
public void println(int level, CharSequence charSequence) {
|
||||
if (level == Log.DEBUG) {
|
||||
SpannableString spannable = new SpannableString(charSequence);
|
||||
spannable.setSpan(new ForegroundColorSpan(0xdd000000), 0, charSequence.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
@@ -60,4 +60,9 @@ public class TimberConsole extends AbstractConsole {
|
||||
public void hide() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTitle(CharSequence title) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import android.util.SparseArray;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.afollestad.materialdialogs.DialogAction;
|
||||
import com.afollestad.materialdialogs.MaterialDialog;
|
||||
@@ -20,16 +21,16 @@ import com.jecelyin.editor.v2.core.widget.TextView;
|
||||
import com.jecelyin.editor.v2.ui.EditorDelegate;
|
||||
import com.jecelyin.editor.v2.view.EditorView;
|
||||
import com.jecelyin.editor.v2.view.menu.MenuDef;
|
||||
import com.stardust.autojs.execution.ScriptExecution;
|
||||
import com.stardust.autojs.script.FileScriptSource;
|
||||
import com.stardust.autojs.script.JsBeautifier;
|
||||
import com.stardust.autojs.script.StringScriptSource;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.external.floating_window.console.FloatingConsole;
|
||||
import com.stardust.scriptdroid.autojs.AutoJs;
|
||||
import com.stardust.scriptdroid.scripts.ScriptFile;
|
||||
import com.stardust.scriptdroid.tool.JsBeautifierFactory;
|
||||
import com.stardust.scriptdroid.tool.MaterialDialogFactory;
|
||||
import com.stardust.scriptdroid.ui.BaseActivity;
|
||||
import com.stardust.scriptdroid.ui.console.ConsoleActivity;
|
||||
import com.stardust.scriptdroid.ui.edit.completion.InputMethodEnhanceBar;
|
||||
import com.stardust.scriptdroid.ui.edit.editor920.Editor920Activity;
|
||||
import com.stardust.scriptdroid.ui.edit.editor920.Editor920Utils;
|
||||
@@ -109,6 +110,7 @@ public class EditActivity extends Editor920Activity {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (intent.getAction().equals(ACTION_ON_RUN_FINISHED)) {
|
||||
mScriptExecution = null;
|
||||
setMenuStatus(R.id.run, MenuDef.STATUS_NORMAL);
|
||||
String msg = intent.getStringExtra(EXTRA_EXCEPTION_MESSAGE);
|
||||
if (msg != null) {
|
||||
@@ -119,6 +121,7 @@ public class EditActivity extends Editor920Activity {
|
||||
}
|
||||
};
|
||||
private JsBeautifier mJsBeautifier = JsBeautifierFactory.getJsBeautify();
|
||||
private ScriptExecution mScriptExecution;
|
||||
|
||||
public void onCreate(Bundle b) {
|
||||
super.onCreate(b);
|
||||
@@ -209,9 +212,9 @@ public class EditActivity extends Editor920Activity {
|
||||
Snackbar.make(mView, R.string.text_start_running, Snackbar.LENGTH_SHORT).show();
|
||||
setMenuStatus(R.id.run, MenuDef.STATUS_DISABLED);
|
||||
if (mFile != null) {
|
||||
ScriptFileOperation.runOnEditView(new FileScriptSource(mName, mFile));
|
||||
mScriptExecution = ScriptFileOperation.runOnEditView(new FileScriptSource(mName, mFile));
|
||||
} else {
|
||||
ScriptFileOperation.runOnEditView(new StringScriptSource(mName, mEditorDelegate.getText()));
|
||||
mScriptExecution = ScriptFileOperation.runOnEditView(new StringScriptSource(mName, mEditorDelegate.getText()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -261,7 +264,7 @@ public class EditActivity extends Editor920Activity {
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_console:
|
||||
startActivity(new Intent(getContext(), ConsoleActivity.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
|
||||
showConsole();
|
||||
return true;
|
||||
case R.id.action_help:
|
||||
HelpCatalogueActivity.showMainCatalogue(this);
|
||||
@@ -272,10 +275,27 @@ public class EditActivity extends Editor920Activity {
|
||||
case R.id.action_open_by_other_apps:
|
||||
openByOtherApps();
|
||||
return true;
|
||||
case R.id.action_force_stop:
|
||||
forceStop();
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
private void showConsole() {
|
||||
if (mScriptExecution != null) {
|
||||
mScriptExecution.getRuntime().console.show();
|
||||
} else {
|
||||
AutoJs.getInstance().getScriptEngineService().getGlobalConsole().show();
|
||||
}
|
||||
}
|
||||
|
||||
private void forceStop() {
|
||||
if (mScriptExecution != null) {
|
||||
mScriptExecution.getEngine().forceStop();
|
||||
}
|
||||
}
|
||||
|
||||
private void openByOtherApps() {
|
||||
if (mFile != null)
|
||||
ScriptFileOperation.openByOtherApps(mFile.getPath());
|
||||
@@ -297,9 +317,15 @@ public class EditActivity extends Editor920Activity {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onException(Exception e) {
|
||||
dialog.dismiss();
|
||||
public void onException(final Exception e) {
|
||||
e.printStackTrace();
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
dialog.dismiss();
|
||||
Toast.makeText(EditActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ public class CodeCompletion implements TextWatcher {
|
||||
mFunctions = functions;
|
||||
}
|
||||
|
||||
private String[] mFunctions = {"toast", "launchPackage", "launch", "launchApp", "click", "longClick", "scrollUp", "scrollDown", "select", "focus", "paste", "input", "sleep", "isStopped", "notStopped", "println", "err", "openConsole", "clearConsole", "shell", "getTexts", "getPackageName", "getActivityName", "setClip", "addAccessibilityDelegate"};
|
||||
private String[] mFunctions = {"toast", "launchPackage", "launch", "launchApp", "click", "longClick", "scrollUp", "scrollDown", "select", "focus", "paste", "input", "sleep", "isStopped", "notStopped", "printf", "err", "openConsole", "clearConsole", "shell", "getTexts", "getPackageName", "getActivityName", "setClip", "addAccessibilityDelegate"};
|
||||
|
||||
private boolean searchCodeCompletion(String str) {
|
||||
Collection<CodeCompletionItem> c = searchWordCompletion(str);
|
||||
|
||||
@@ -19,12 +19,15 @@ import com.stardust.scriptdroid.service.AccessibilityWatchDogService;
|
||||
import com.stardust.scriptdroid.tool.AccessibilityServiceTool;
|
||||
import com.stardust.scriptdroid.ui.console.ConsoleActivity;
|
||||
import com.stardust.scriptdroid.ui.help.HelpCatalogueActivity;
|
||||
import com.stardust.util.UnderuseExecutors;
|
||||
import com.stardust.view.ViewBinder;
|
||||
import com.stardust.view.ViewBinding;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/30.
|
||||
@@ -38,7 +41,8 @@ public class SlideMenuFragment extends Fragment {
|
||||
activity.getSupportFragmentManager().beginTransaction().replace(viewId, fragment).commit();
|
||||
}
|
||||
|
||||
private SwitchCompat mAutoOperateServiceSwitch, mFloatingWindowSwitch;
|
||||
private SwitchCompat mAccessibilityServiceSwitch, mFloatingWindowSwitch;
|
||||
private Executor mExecutor = UnderuseExecutors.getExecutor();
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
@@ -67,17 +71,28 @@ public class SlideMenuFragment extends Fragment {
|
||||
|
||||
|
||||
private void syncSwitchState() {
|
||||
mAutoOperateServiceSwitch.postDelayed(new Runnable() {
|
||||
mAccessibilityServiceSwitch.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mAutoOperateServiceSwitch.setChecked(AccessibilityWatchDogService.isEnable());
|
||||
mExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final boolean checked = AccessibilityWatchDogService.isEnable();
|
||||
mAccessibilityServiceSwitch.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mAccessibilityServiceSwitch.setChecked(checked);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}, 450);
|
||||
mFloatingWindowSwitch.setChecked(FloatingWindowManger.isFloatingWindowShowing());
|
||||
}
|
||||
|
||||
private void setUpSwitchCompat() {
|
||||
mAutoOperateServiceSwitch = $(R.id.sw_auto_operate_service);
|
||||
mAccessibilityServiceSwitch = $(R.id.sw_auto_operate_service);
|
||||
mFloatingWindowSwitch = $(R.id.sw_floating_window);
|
||||
}
|
||||
|
||||
@@ -94,7 +109,7 @@ public class SlideMenuFragment extends Fragment {
|
||||
|
||||
@ViewBinding.Click(R.id.auto_operate_service)
|
||||
private void clickAutoOperateServiceSwitch() {
|
||||
mAutoOperateServiceSwitch.toggle();
|
||||
mAccessibilityServiceSwitch.toggle();
|
||||
}
|
||||
|
||||
@ViewBinding.Check(R.id.sw_auto_operate_service)
|
||||
|
||||
@@ -4,8 +4,10 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
|
||||
import com.stardust.autojs.ScriptExecutionListener;
|
||||
import com.stardust.autojs.engine.JavaScriptEngine;
|
||||
import com.stardust.autojs.execution.ScriptExecution;
|
||||
import com.stardust.autojs.execution.ScriptExecutionListener;
|
||||
import com.stardust.autojs.execution.SimpleScriptExecutionListener;
|
||||
import com.stardust.autojs.runtime.ScriptInterruptedException;
|
||||
import com.stardust.autojs.script.FileScriptSource;
|
||||
import com.stardust.autojs.script.ScriptSource;
|
||||
import com.stardust.autojs.script.StringScriptSource;
|
||||
@@ -30,23 +32,20 @@ public abstract class ScriptFileOperation {
|
||||
public static final String EXTRA_EXCEPTION_MESSAGE = "EXTRA_EXCEPTION_MESSAGE";
|
||||
|
||||
|
||||
private static final ScriptExecutionListener SCRIPT_EXECUTION_LISTENER = new ScriptExecutionListener() {
|
||||
private static final ScriptExecutionListener RUN_ON_EDIT_VIEW_SCRIPT_EXECUTION_LISTENER = new SimpleScriptExecutionListener() {
|
||||
|
||||
@Override
|
||||
public void onStart(JavaScriptEngine engine, ScriptSource source) {
|
||||
AutoJs.getInstance().getScriptEngineService().getDefaultScriptExecutionListener().onStart(engine, source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(JavaScriptEngine engine, ScriptSource source, Object result) {
|
||||
public void onSuccess(ScriptExecution execution, Object result) {
|
||||
App.getApp().sendBroadcast(new Intent(ACTION_ON_RUN_FINISHED));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onException(JavaScriptEngine engine, ScriptSource source, Exception e) {
|
||||
public void onException(ScriptExecution execution, Exception e) {
|
||||
if (ScriptInterruptedException.causedByInterrupted(e)) {
|
||||
return;
|
||||
}
|
||||
App.getApp().sendBroadcast(new Intent(ACTION_ON_RUN_FINISHED)
|
||||
.putExtra(EXTRA_EXCEPTION_MESSAGE, e.getMessage()));
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
};
|
||||
@@ -78,8 +77,8 @@ public abstract class ScriptFileOperation {
|
||||
AutoJs.getInstance().getScriptEngineService().execute(new StringScriptSource(file.name, AssetsCache.get(context.getAssets(), file.path)));
|
||||
}
|
||||
|
||||
public static void runOnEditView(ScriptSource scriptSource) {
|
||||
AutoJs.getInstance().getScriptEngineService().execute(scriptSource, SCRIPT_EXECUTION_LISTENER);
|
||||
public static ScriptExecution runOnEditView(ScriptSource scriptSource) {
|
||||
return AutoJs.getInstance().getScriptEngineService().execute(scriptSource, RUN_ON_EDIT_VIEW_SCRIPT_EXECUTION_LISTENER);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,9 +1,7 @@
|
||||
package com.stardust.scriptdroid.ui.main.task;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.IntDef;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.support.v7.widget.ThemeColorRecyclerView;
|
||||
import android.util.AttributeSet;
|
||||
@@ -14,6 +12,9 @@ import android.widget.TextView;
|
||||
import android.workground.WrapContentLinearLayoutManager;
|
||||
|
||||
import com.stardust.autojs.ScriptEngineService;
|
||||
import com.stardust.autojs.execution.ScriptExecution;
|
||||
import com.stardust.autojs.execution.ScriptExecutionListener;
|
||||
import com.stardust.autojs.execution.SimpleScriptExecutionListener;
|
||||
import com.stardust.autojs.engine.JavaScriptEngine;
|
||||
import com.stardust.autojs.engine.JavaScriptEngineManager;
|
||||
import com.stardust.autojs.script.ScriptSource;
|
||||
@@ -22,7 +23,6 @@ import com.stardust.scriptdroid.autojs.AutoJs;
|
||||
import com.yqritc.recyclerviewflexibledivider.HorizontalDividerItemDecoration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -51,6 +51,23 @@ public class TaskListRecyclerView extends ThemeColorRecyclerView implements Java
|
||||
private final List<JavaScriptEngine> mScriptEngines = new ArrayList<>();
|
||||
private Adapter mAdapter;
|
||||
private final ScriptEngineService mScriptEngineService = AutoJs.getInstance().getScriptEngineService();
|
||||
private ScriptExecutionListener mScriptExecutionListener = new SimpleScriptExecutionListener() {
|
||||
@Override
|
||||
public void onStart(final ScriptExecution execution) {
|
||||
post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int position = mScriptEngines.indexOf(execution.getEngine());
|
||||
if (position >= 0) {
|
||||
mAdapter.notifyItemChanged(position);
|
||||
} else {
|
||||
updateEngineList();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
public TaskListRecyclerView(Context context) {
|
||||
super(context);
|
||||
@@ -89,18 +106,22 @@ public class TaskListRecyclerView extends ThemeColorRecyclerView implements Java
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
mScriptEngineService.registerEngineLifecycleCallback(this);
|
||||
AutoJs.getInstance().getScriptEngineService().registerGlobalScriptExecutionListener(mScriptExecutionListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onWindowVisibilityChanged(int visibility) {
|
||||
super.onWindowVisibilityChanged(visibility);
|
||||
updateEngineList();
|
||||
if (visibility == VISIBLE) {
|
||||
updateEngineList();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow();
|
||||
mScriptEngineService.unregisterEngineLifecycleCallback(this);
|
||||
AutoJs.getInstance().getScriptEngineService().unregisterGlobalScriptExecutionListener(mScriptExecutionListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -122,8 +143,13 @@ public class TaskListRecyclerView extends ThemeColorRecyclerView implements Java
|
||||
@Override
|
||||
public void run() {
|
||||
final int i = mScriptEngines.indexOf(engine);
|
||||
mScriptEngines.remove(i);
|
||||
mAdapter.notifyItemRemoved(i);
|
||||
if (i >= 0) {
|
||||
mScriptEngines.remove(i);
|
||||
mAdapter.notifyItemRemoved(i);
|
||||
} else {
|
||||
updateEngineList();
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user