feat: java class searching and import; fix: editor crash on edit when file is too large
This commit is contained in:
BIN
.idea/caches/build_file_checksums.ser
generated
BIN
.idea/caches/build_file_checksums.ser
generated
Binary file not shown.
@@ -8,8 +8,8 @@ android {
|
|||||||
applicationId "org.autojs.autojs"
|
applicationId "org.autojs.autojs"
|
||||||
minSdkVersion 17
|
minSdkVersion 17
|
||||||
targetSdkVersion 23
|
targetSdkVersion 23
|
||||||
versionCode 413
|
versionCode 414
|
||||||
versionName "4.0.2 Alpha8"
|
versionName "4.0.2 Alpha9"
|
||||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
multiDexEnabled true
|
multiDexEnabled true
|
||||||
ndk {
|
ndk {
|
||||||
|
|||||||
1
app/src/main/assets/indices/all_android_classes.json
Normal file
1
app/src/main/assets/indices/all_android_classes.json
Normal file
File diff suppressed because one or more lines are too long
@@ -30,7 +30,6 @@ import org.autojs.autojs.ui.error.ErrorReportActivity;
|
|||||||
|
|
||||||
import com.stardust.theme.ThemeColor;
|
import com.stardust.theme.ThemeColor;
|
||||||
import com.stardust.theme.ThemeColorManager;
|
import com.stardust.theme.ThemeColorManager;
|
||||||
import com.tencent.bugly.Bugly;
|
|
||||||
import com.tencent.bugly.crashreport.CrashReport;
|
import com.tencent.bugly.crashreport.CrashReport;
|
||||||
|
|
||||||
|
|
||||||
@@ -77,7 +76,7 @@ public class App extends MultiDexApplication {
|
|||||||
|
|
||||||
CrashReport.initCrashReport(getApplicationContext(), BUGLY_APP_ID, false, strategy);
|
CrashReport.initCrashReport(getApplicationContext(), BUGLY_APP_ID, false, strategy);
|
||||||
|
|
||||||
crashHandler.setDefaultHandler(Thread.getDefaultUncaughtExceptionHandler());
|
crashHandler.setBuglyHandler(Thread.getDefaultUncaughtExceptionHandler());
|
||||||
Thread.setDefaultUncaughtExceptionHandler(crashHandler);
|
Thread.setDefaultUncaughtExceptionHandler(crashHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import org.autojs.autojs.ui.widget.SimpleTextWatcher;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -20,6 +21,7 @@ public class AnyWordsCompletion implements SimpleTextWatcher.AfterTextChangedLis
|
|||||||
private static final String PATTERN = "[\\W]";
|
private static final String PATTERN = "[\\W]";
|
||||||
private ExecutorService mExecutorService;
|
private ExecutorService mExecutorService;
|
||||||
private volatile DictionaryTree<String> mDictionaryTree;
|
private volatile DictionaryTree<String> mDictionaryTree;
|
||||||
|
private AtomicInteger mExecuteId = new AtomicInteger();
|
||||||
|
|
||||||
public AnyWordsCompletion(ExecutorService executorService) {
|
public AnyWordsCompletion(ExecutorService executorService) {
|
||||||
mExecutorService = executorService;
|
mExecutorService = executorService;
|
||||||
@@ -27,13 +29,21 @@ public class AnyWordsCompletion implements SimpleTextWatcher.AfterTextChangedLis
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void afterTextChanged(Editable s) {
|
public void afterTextChanged(Editable s) {
|
||||||
mExecutorService.execute(() -> splitWords(s.toString()));
|
String str = s.toString();
|
||||||
|
int id = mExecuteId.incrementAndGet();
|
||||||
|
mExecutorService.execute(() -> splitWords(id, str));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void splitWords(String s) {
|
private void splitWords(int id, String s) {
|
||||||
|
if(id != mExecuteId.get()){
|
||||||
|
return;
|
||||||
|
}
|
||||||
DictionaryTree<String> tree = new DictionaryTree<>();
|
DictionaryTree<String> tree = new DictionaryTree<>();
|
||||||
String[] words = s.split(PATTERN);
|
String[] words = s.split(PATTERN);
|
||||||
for (String word : words) {
|
for (String word : words) {
|
||||||
|
if(id != mExecuteId.get()){
|
||||||
|
return;
|
||||||
|
}
|
||||||
tree.putWord(word, word);
|
tree.putWord(word, word);
|
||||||
}
|
}
|
||||||
mDictionaryTree = tree;
|
mDictionaryTree = tree;
|
||||||
|
|||||||
@@ -1,18 +1,22 @@
|
|||||||
package org.autojs.autojs.model.autocomplete;
|
package org.autojs.autojs.model.autocomplete;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
|
|
||||||
import org.autojs.autojs.model.indices.Module;
|
import org.autojs.autojs.model.indices.Module;
|
||||||
import org.autojs.autojs.model.indices.Modules;
|
import org.autojs.autojs.model.indices.Modules;
|
||||||
import org.autojs.autojs.model.indices.Property;
|
import org.autojs.autojs.model.indices.Property;
|
||||||
import org.autojs.autojs.ui.widget.SimpleTextWatcher;
|
import org.autojs.autojs.ui.widget.SimpleTextWatcher;
|
||||||
|
import org.mozilla.javascript.ast.Loop;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
@@ -39,6 +43,8 @@ public class AutoCompletion {
|
|||||||
private AutoCompleteCallback mAutoCompleteCallback;
|
private AutoCompleteCallback mAutoCompleteCallback;
|
||||||
private ExecutorService mExecutorService = Executors.newSingleThreadExecutor();
|
private ExecutorService mExecutorService = Executors.newSingleThreadExecutor();
|
||||||
private AnyWordsCompletion mAnyWordsCompletion;
|
private AnyWordsCompletion mAnyWordsCompletion;
|
||||||
|
private AtomicInteger mExecuteId = new AtomicInteger();
|
||||||
|
private Handler mHandler = new Handler(Looper.getMainLooper());
|
||||||
|
|
||||||
public AutoCompletion(Context context, EditText editText) {
|
public AutoCompletion(Context context, EditText editText) {
|
||||||
buildDictionaryTree(context);
|
buildDictionaryTree(context);
|
||||||
@@ -80,10 +86,19 @@ public class AutoCompletion {
|
|||||||
if (mPropertyPrefill == null && module == null)
|
if (mPropertyPrefill == null && module == null)
|
||||||
return;
|
return;
|
||||||
String prefill = mPropertyPrefill;
|
String prefill = mPropertyPrefill;
|
||||||
|
int id = mExecuteId.incrementAndGet();
|
||||||
mExecutorService.execute(() -> {
|
mExecutorService.execute(() -> {
|
||||||
|
if (id != mExecuteId.get())
|
||||||
|
return;
|
||||||
List<CodeCompletion> completions = findCodeCompletion(module, prefill);
|
List<CodeCompletion> completions = findCodeCompletion(module, prefill);
|
||||||
CodeCompletions codeCompletions = new CodeCompletions(cursor, completions);
|
CodeCompletions codeCompletions = new CodeCompletions(cursor, completions);
|
||||||
mAutoCompleteCallback.updateCodeCompletion(codeCompletions);
|
if (id != mExecuteId.get())
|
||||||
|
return;
|
||||||
|
mHandler.post(() -> {
|
||||||
|
if (id != mExecuteId.get())
|
||||||
|
return;
|
||||||
|
mAutoCompleteCallback.updateCodeCompletion(codeCompletions);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package org.autojs.autojs.model.indices;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
public class AndroidClass {
|
||||||
|
|
||||||
|
@SerializedName("class_name")
|
||||||
|
private String mClassName;
|
||||||
|
@SerializedName("package_name")
|
||||||
|
private String mPackageName;
|
||||||
|
@SerializedName("full_name")
|
||||||
|
private String mFullName;
|
||||||
|
|
||||||
|
public String getClassName() {
|
||||||
|
return mClassName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClassName(String className) {
|
||||||
|
mClassName = className;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPackageName() {
|
||||||
|
return mPackageName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPackageName(String packageName) {
|
||||||
|
mPackageName = packageName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFullName() {
|
||||||
|
return mFullName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFullName(String fullName) {
|
||||||
|
mFullName = fullName;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
package org.autojs.autojs.model.indices;
|
||||||
|
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
|
||||||
|
import org.autojs.autojs.tool.EmptyObservers;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.Reader;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import io.reactivex.Observable;
|
||||||
|
import io.reactivex.Single;
|
||||||
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
|
import io.reactivex.schedulers.Schedulers;
|
||||||
|
|
||||||
|
public class AndroidClassIndices {
|
||||||
|
|
||||||
|
static class LoadException extends RuntimeException {
|
||||||
|
|
||||||
|
LoadException(Throwable cause) {
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("StaticFieldLeak")
|
||||||
|
private static AndroidClassIndices sInstance;
|
||||||
|
|
||||||
|
private static Type ANDROID_CLASS_LIST_TYPE = new TypeToken<List<AndroidClass>>() {
|
||||||
|
}.getType();
|
||||||
|
//packageName -> package classes
|
||||||
|
private LinkedHashMap<String, ArrayList<ClassSearchingItem>> mPackages = new LinkedHashMap<>();
|
||||||
|
private Context mContext;
|
||||||
|
private ExecutorService mSingleThreadExecutor = new ThreadPoolExecutor(1, 1,
|
||||||
|
2, TimeUnit.MINUTES, new LinkedBlockingQueue<>());
|
||||||
|
private Throwable mLoadThrowable;
|
||||||
|
|
||||||
|
|
||||||
|
protected AndroidClassIndices(Context context) {
|
||||||
|
mContext = context.getApplicationContext();
|
||||||
|
load("indices/all_android_classes.json");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AndroidClassIndices getInstance(Context context) {
|
||||||
|
if (sInstance == null) {
|
||||||
|
sInstance = new AndroidClassIndices(context);
|
||||||
|
}
|
||||||
|
return sInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Single<List<ClassSearchingItem>> search(String keywords) {
|
||||||
|
return Single.fromCallable(() -> {
|
||||||
|
if (mPackages.isEmpty() && mLoadThrowable != null) {
|
||||||
|
throw new LoadException(mLoadThrowable);
|
||||||
|
}
|
||||||
|
return mPackages.values();
|
||||||
|
})
|
||||||
|
.map(packages -> search(packages, keywords))
|
||||||
|
.subscribeOn(Schedulers.from(mSingleThreadExecutor));
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<ClassSearchingItem> search(Collection<ArrayList<ClassSearchingItem>> packages, String keywords) {
|
||||||
|
List<ClassSearchingItem> result = new ArrayList<>();
|
||||||
|
if (TextUtils.isEmpty(keywords)) {
|
||||||
|
for (ArrayList<ClassSearchingItem> packageClasses : packages) {
|
||||||
|
result.addAll(packageClasses);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (ArrayList<ClassSearchingItem> packageClasses : packages) {
|
||||||
|
for (ClassSearchingItem item : packageClasses) {
|
||||||
|
if (item.matches(keywords)) {
|
||||||
|
result.add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Collections.sort(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("CheckResult")
|
||||||
|
private void load(String assetsPath) {
|
||||||
|
Observable.just(assetsPath)
|
||||||
|
.map(path -> mContext.getAssets().open(path))
|
||||||
|
.map(InputStreamReader::new)
|
||||||
|
.doOnNext(this::load)
|
||||||
|
.subscribeOn(Schedulers.from(mSingleThreadExecutor))
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(EmptyObservers.consumer(), t -> {
|
||||||
|
mLoadThrowable = t;
|
||||||
|
t.printStackTrace();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void load(Reader reader) throws IOException {
|
||||||
|
try {
|
||||||
|
Gson gson = new Gson();
|
||||||
|
ArrayList<AndroidClass> classes = gson.fromJson(reader, ANDROID_CLASS_LIST_TYPE);
|
||||||
|
load(classes);
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
throw e;
|
||||||
|
} finally {
|
||||||
|
reader.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void load(ArrayList<AndroidClass> classes) {
|
||||||
|
mPackages.clear();
|
||||||
|
for (AndroidClass clazz : classes) {
|
||||||
|
String packageName = clazz.getPackageName();
|
||||||
|
ArrayList<ClassSearchingItem> packageClasses = mPackages.get(packageName);
|
||||||
|
if (packageClasses == null) {
|
||||||
|
packageClasses = new ArrayList<>();
|
||||||
|
mPackages.put(packageName, packageClasses);
|
||||||
|
packageClasses.add(new ClassSearchingItem.PackageItem(packageName));
|
||||||
|
}
|
||||||
|
packageClasses.add(new ClassSearchingItem.ClassItem(clazz));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,160 @@
|
|||||||
|
package org.autojs.autojs.model.indices;
|
||||||
|
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
public abstract class ClassSearchingItem implements Comparable<ClassSearchingItem> {
|
||||||
|
|
||||||
|
static final String BASE_URL = "http://www.android-doc.com/reference/";
|
||||||
|
|
||||||
|
protected int rank;
|
||||||
|
|
||||||
|
public abstract boolean matches(String keywords);
|
||||||
|
|
||||||
|
public abstract String getLabel();
|
||||||
|
|
||||||
|
public abstract String getUrl();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(@NonNull ClassSearchingItem o) {
|
||||||
|
return Integer.compare(o.rank, rank);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int rank(String words, String keywords) {
|
||||||
|
int length = words.length();
|
||||||
|
int i = words.indexOf(keywords);
|
||||||
|
if (i < 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
//full matches
|
||||||
|
if (i == 0 && keywords.length() == length) {
|
||||||
|
return 10;
|
||||||
|
}
|
||||||
|
//words ends with keywords
|
||||||
|
if (i + keywords.length() == length) {
|
||||||
|
if (i > 0 && words.charAt(i - 1) == '.') {
|
||||||
|
return 9;
|
||||||
|
}
|
||||||
|
return 8;
|
||||||
|
}
|
||||||
|
//package starts with keywords
|
||||||
|
if (i > 0 && words.charAt(i - 1) == '.') {
|
||||||
|
//package equals keywords
|
||||||
|
if (i < length - 1 && words.charAt(i + 1) == '.') {
|
||||||
|
return 7;
|
||||||
|
}
|
||||||
|
return 6;
|
||||||
|
}
|
||||||
|
//package ends with keywords
|
||||||
|
if (i < length - 1 && words.charAt(i + 1) == '.') {
|
||||||
|
return 6;
|
||||||
|
}
|
||||||
|
if (i == 0) {
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "ClassSearchingItem{" + getLabel() + "}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract String getImportText();
|
||||||
|
|
||||||
|
public static class ClassItem extends ClassSearchingItem {
|
||||||
|
|
||||||
|
private final AndroidClass mAndroidClass;
|
||||||
|
|
||||||
|
public ClassItem(AndroidClass androidClass) {
|
||||||
|
mAndroidClass = androidClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean matches(String keywords) {
|
||||||
|
rank = rank(mAndroidClass.getFullName(), keywords);
|
||||||
|
Log.d("ClassSearching", "rank = " + rank + ", word = " + mAndroidClass.getFullName());
|
||||||
|
return rank > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getLabel() {
|
||||||
|
return String.format("%s (%s)", mAndroidClass.getClassName(), mAndroidClass.getPackageName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUrl() {
|
||||||
|
return BASE_URL + mAndroidClass.getPackageName().replace('.', '/')
|
||||||
|
+ "/" + mAndroidClass.getClassName() + ".html";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getImportText() {
|
||||||
|
return String.format("importClass(%s)", mAndroidClass.getFullName());
|
||||||
|
}
|
||||||
|
|
||||||
|
public AndroidClass getAndroidClass() {
|
||||||
|
return mAndroidClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
ClassItem classItem = (ClassItem) o;
|
||||||
|
return mAndroidClass.equals(classItem.mAndroidClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return mAndroidClass.hashCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PackageItem extends ClassSearchingItem {
|
||||||
|
|
||||||
|
private final String mPackageName;
|
||||||
|
|
||||||
|
public PackageItem(String packageName) {
|
||||||
|
mPackageName = packageName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean matches(String keywords) {
|
||||||
|
rank = rank(mPackageName, keywords);
|
||||||
|
return rank > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getLabel() {
|
||||||
|
return mPackageName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUrl() {
|
||||||
|
return BASE_URL + mPackageName.replace('.', '/') + "/package-summary.html";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getImportText() {
|
||||||
|
return String.format("importPackage(%s)", mPackageName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPackageName() {
|
||||||
|
return mPackageName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
PackageItem that = (PackageItem) o;
|
||||||
|
return mPackageName.equals(that.mPackageName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return mPackageName.hashCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,25 +9,16 @@ import android.content.Intent;
|
|||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.View;
|
|
||||||
import android.view.WindowManager;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import com.stardust.app.GlobalAppContext;
|
import com.stardust.app.GlobalAppContext;
|
||||||
|
|
||||||
import org.autojs.autojs.App;
|
|
||||||
import org.autojs.autojs.BuildConfig;
|
import org.autojs.autojs.BuildConfig;
|
||||||
import org.autojs.autojs.R;
|
import org.mozilla.javascript.RhinoException;
|
||||||
|
|
||||||
import com.stardust.util.IntentUtil;
|
|
||||||
import com.stardust.view.accessibility.AccessibilityService;
|
import com.stardust.view.accessibility.AccessibilityService;
|
||||||
import com.tencent.bugly.Bugly;
|
|
||||||
import com.tencent.bugly.crashreport.BuglyLog;
|
import com.tencent.bugly.crashreport.BuglyLog;
|
||||||
import com.tencent.bugly.crashreport.CrashReport;
|
import com.tencent.bugly.crashreport.CrashReport;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.io.StringWriter;
|
|
||||||
import java.lang.Thread.UncaughtExceptionHandler;
|
import java.lang.Thread.UncaughtExceptionHandler;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@@ -36,21 +27,24 @@ public class CrashHandler extends CrashReport.CrashHandleCallback implements Unc
|
|||||||
private static int crashCount = 0;
|
private static int crashCount = 0;
|
||||||
private static long firstCrashMillis = 0;
|
private static long firstCrashMillis = 0;
|
||||||
private final Class<?> mErrorReportClass;
|
private final Class<?> mErrorReportClass;
|
||||||
private UncaughtExceptionHandler mDefaultHandler;
|
private UncaughtExceptionHandler mBuglyHandler;
|
||||||
|
private UncaughtExceptionHandler mSystemHandler;
|
||||||
|
|
||||||
public CrashHandler(Class<?> errorReportClass) {
|
public CrashHandler(Class<?> errorReportClass) {
|
||||||
this.mErrorReportClass = errorReportClass;
|
this.mErrorReportClass = errorReportClass;
|
||||||
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
|
mSystemHandler = Thread.getDefaultUncaughtExceptionHandler();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDefaultHandler(UncaughtExceptionHandler defaultHandler) {
|
public void setBuglyHandler(UncaughtExceptionHandler buglyHandler) {
|
||||||
mDefaultHandler = defaultHandler;
|
mBuglyHandler = buglyHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void uncaughtException(Thread thread, Throwable ex) {
|
public void uncaughtException(Thread thread, Throwable ex) {
|
||||||
Log.e(TAG, "Uncaught Exception", ex);
|
Log.e(TAG, "Uncaught Exception", ex);
|
||||||
if (thread != Looper.getMainLooper().getThread()) {
|
if (thread != Looper.getMainLooper().getThread()) {
|
||||||
CrashReport.postCatchedException(ex, thread);
|
if(!(ex instanceof RhinoException)){
|
||||||
|
CrashReport.postCatchedException(ex, thread);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
AccessibilityService service = AccessibilityService.getInstance();
|
AccessibilityService service = AccessibilityService.getInstance();
|
||||||
@@ -60,7 +54,11 @@ public class CrashHandler extends CrashReport.CrashHandleCallback implements Unc
|
|||||||
} else {
|
} else {
|
||||||
BuglyLog.d(TAG, "cannot disable service: " + service);
|
BuglyLog.d(TAG, "cannot disable service: " + service);
|
||||||
}
|
}
|
||||||
mDefaultHandler.uncaughtException(thread, ex);
|
if (BuildConfig.DEBUG) {
|
||||||
|
mSystemHandler.uncaughtException(thread, ex);
|
||||||
|
} else {
|
||||||
|
mBuglyHandler.uncaughtException(thread, ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -0,0 +1,133 @@
|
|||||||
|
package org.autojs.autojs.ui.edit;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.v7.widget.LinearLayoutManager;
|
||||||
|
import android.support.v7.widget.RecyclerView;
|
||||||
|
import android.view.ContextThemeWrapper;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import com.afollestad.materialdialogs.MaterialDialog;
|
||||||
|
|
||||||
|
import org.autojs.autojs.R;
|
||||||
|
import org.autojs.autojs.model.indices.AndroidClassIndices;
|
||||||
|
import org.autojs.autojs.model.indices.ClassSearchingItem;
|
||||||
|
import org.autojs.autojs.theme.dialog.ThemeColorMaterialDialogBuilder;
|
||||||
|
import org.autojs.autojs.tool.MaterialDialogFactory;
|
||||||
|
import org.autojs.autojs.ui.widget.AutoAdapter;
|
||||||
|
import org.autojs.autojs.ui.widget.BindableViewHolder;
|
||||||
|
import org.autojs.autojs.ui.widget.SimpleTextWatcher;
|
||||||
|
|
||||||
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
|
import me.zhanghai.android.materialprogressbar.MaterialProgressBar;
|
||||||
|
|
||||||
|
public class ClassSearchDialogBuilder extends ThemeColorMaterialDialogBuilder {
|
||||||
|
|
||||||
|
public interface OnItemClickListener {
|
||||||
|
void onItemClick(MaterialDialog dialog, ClassSearchingItem item, int position);
|
||||||
|
}
|
||||||
|
|
||||||
|
private AutoAdapter<ClassSearchingItem> mResultListAdapter;
|
||||||
|
private MaterialProgressBar mProgressBar;
|
||||||
|
private EditText mKeywords;
|
||||||
|
private OnItemClickListener mOnItemClickListener;
|
||||||
|
private int mSearchId = 0;
|
||||||
|
private final Handler mHandler;
|
||||||
|
private MaterialDialog mDialog;
|
||||||
|
|
||||||
|
|
||||||
|
public ClassSearchDialogBuilder(@NonNull Context context) {
|
||||||
|
super(new ContextThemeWrapper(context, R.style.AppTheme));
|
||||||
|
mHandler = new Handler();
|
||||||
|
initViews(getContext());
|
||||||
|
AndroidClassIndices.getInstance(getContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClassSearchDialogBuilder setQuery(String text) {
|
||||||
|
mKeywords.setText(text);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClassSearchDialogBuilder itemClick(OnItemClickListener listener) {
|
||||||
|
mOnItemClickListener = listener;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initViews(Context context) {
|
||||||
|
View view = View.inflate(context, R.layout.dialog_class_search, null);
|
||||||
|
customView(view, true);
|
||||||
|
mKeywords = view.findViewById(R.id.keywords);
|
||||||
|
mKeywords.addTextChangedListener(new SimpleTextWatcher(this::postSearch));
|
||||||
|
mProgressBar = view.findViewById(R.id.progress_bar);
|
||||||
|
initResultList(view, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initResultList(View view, Context context) {
|
||||||
|
RecyclerView resultList = view.findViewById(R.id.result_list);
|
||||||
|
resultList.setLayoutManager(new LinearLayoutManager(context));
|
||||||
|
mResultListAdapter = new AutoAdapter<>(ClassSearchingItemViewHolder::new,
|
||||||
|
R.layout.item_class_searching_result_list);
|
||||||
|
resultList.setAdapter(mResultListAdapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MaterialDialog build() {
|
||||||
|
mDialog = super.build();
|
||||||
|
return mDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void postSearch(CharSequence s) {
|
||||||
|
mSearchId++;
|
||||||
|
int searchId = mSearchId;
|
||||||
|
mHandler.postDelayed(() -> {
|
||||||
|
if (searchId == mSearchId) {
|
||||||
|
search(s);
|
||||||
|
}
|
||||||
|
}, 300);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("CheckResult")
|
||||||
|
private void search(CharSequence s) {
|
||||||
|
mResultListAdapter.removeAll();
|
||||||
|
mProgressBar.setVisibility(View.VISIBLE);
|
||||||
|
String keywords = s.toString();
|
||||||
|
AndroidClassIndices.getInstance(getContext())
|
||||||
|
.search(keywords)
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(result -> {
|
||||||
|
mResultListAdapter.notifyDataSetChanged(result);
|
||||||
|
mProgressBar.setVisibility(View.GONE);
|
||||||
|
}, t -> {
|
||||||
|
t.printStackTrace();
|
||||||
|
mProgressBar.setVisibility(View.GONE);
|
||||||
|
Toast.makeText(context, t.getMessage(), Toast.LENGTH_LONG).show();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ClassSearchingItemViewHolder extends BindableViewHolder<ClassSearchingItem> {
|
||||||
|
|
||||||
|
private final TextView mLabel;
|
||||||
|
|
||||||
|
ClassSearchingItemViewHolder(View itemView) {
|
||||||
|
super(itemView);
|
||||||
|
mLabel = itemView.findViewById(R.id.label);
|
||||||
|
itemView.setOnClickListener(v -> {
|
||||||
|
int pos = getAdapterPosition();
|
||||||
|
if (mOnItemClickListener != null) {
|
||||||
|
mOnItemClickListener.onItemClick(mDialog, mResultListAdapter.get(pos), pos);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void bind(ClassSearchingItem data, int position) {
|
||||||
|
mLabel.setText(data.getLabel());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ import android.content.Context;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import android.view.ActionMode;
|
import android.view.ActionMode;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
@@ -43,7 +44,8 @@ import static org.autojs.autojs.ui.edit.EditorView.EXTRA_READ_ONLY;
|
|||||||
* Created by Stardust on 2017/1/29.
|
* Created by Stardust on 2017/1/29.
|
||||||
*/
|
*/
|
||||||
@EActivity(R.layout.activity_edit)
|
@EActivity(R.layout.activity_edit)
|
||||||
public class EditActivity extends BaseActivity implements OnActivityResultDelegate.DelegateHost, PermissionRequestProxyActivity {
|
public class
|
||||||
|
EditActivity extends BaseActivity implements OnActivityResultDelegate.DelegateHost, PermissionRequestProxyActivity {
|
||||||
|
|
||||||
private OnActivityResultDelegate.Mediator mMediator = new OnActivityResultDelegate.Mediator();
|
private OnActivityResultDelegate.Mediator mMediator = new OnActivityResultDelegate.Mediator();
|
||||||
|
|
||||||
@@ -84,6 +86,18 @@ public class EditActivity extends BaseActivity implements OnActivityResultDelega
|
|||||||
setUpToolbar();
|
setUpToolbar();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public ActionMode onWindowStartingActionMode(ActionMode.Callback callback) {
|
||||||
|
return super.onWindowStartingActionMode(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public ActionMode onWindowStartingActionMode(ActionMode.Callback callback, int type) {
|
||||||
|
return super.onWindowStartingActionMode(callback, type);
|
||||||
|
}
|
||||||
|
|
||||||
private void onLoadFileError(String message) {
|
private void onLoadFileError(String message) {
|
||||||
new ThemeColorMaterialDialogBuilder(this)
|
new ThemeColorMaterialDialogBuilder(this)
|
||||||
.title(getString(R.string.text_cannot_read_file))
|
.title(getString(R.string.text_cannot_read_file))
|
||||||
@@ -117,6 +131,13 @@ public class EditActivity extends BaseActivity implements OnActivityResultDelega
|
|||||||
return super.onPrepareOptionsMenu(menu);
|
return super.onPrepareOptionsMenu(menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean onPrepareActionMode(Menu menu) {
|
||||||
|
boolean isScriptRunning = mEditorView.getScriptExecutionId() != ScriptExecution.NO_ID;
|
||||||
|
MenuItem forceStopItem = menu.findItem(R.id.action_force_stop);
|
||||||
|
forceStopItem.setEnabled(isScriptRunning);
|
||||||
|
return super.onPrepareOptionsMenu(menu);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onActionModeStarted(ActionMode mode) {
|
public void onActionModeStarted(ActionMode mode) {
|
||||||
Menu menu = mode.getMenu();
|
Menu menu = mode.getMenu();
|
||||||
|
|||||||
@@ -1,15 +1,21 @@
|
|||||||
package org.autojs.autojs.ui.edit;
|
package org.autojs.autojs.ui.edit;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.support.design.widget.Snackbar;
|
import android.support.design.widget.Snackbar;
|
||||||
import android.text.InputType;
|
import android.text.InputType;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.widget.TextView;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import com.afollestad.materialdialogs.MaterialDialog;
|
||||||
|
import com.stardust.autojs.script.JavaScriptSource;
|
||||||
|
import com.stardust.autojs.script.ScriptSource;
|
||||||
import com.stardust.pio.PFiles;
|
import com.stardust.pio.PFiles;
|
||||||
|
|
||||||
import org.autojs.autojs.R;
|
import org.autojs.autojs.R;
|
||||||
|
import org.autojs.autojs.model.indices.AndroidClass;
|
||||||
|
import org.autojs.autojs.model.indices.ClassSearchingItem;
|
||||||
import org.autojs.autojs.ui.build.BuildActivity;
|
import org.autojs.autojs.ui.build.BuildActivity;
|
||||||
import org.autojs.autojs.ui.build.BuildActivity_;
|
import org.autojs.autojs.ui.build.BuildActivity_;
|
||||||
import org.autojs.autojs.ui.common.NotAskAgainDialog;
|
import org.autojs.autojs.ui.common.NotAskAgainDialog;
|
||||||
@@ -18,6 +24,7 @@ import org.autojs.autojs.ui.log.LogActivity_;
|
|||||||
import org.autojs.autojs.theme.dialog.ThemeColorMaterialDialogBuilder;
|
import org.autojs.autojs.theme.dialog.ThemeColorMaterialDialogBuilder;
|
||||||
|
|
||||||
import com.stardust.util.ClipboardUtil;
|
import com.stardust.util.ClipboardUtil;
|
||||||
|
import com.stardust.util.IntentUtil;
|
||||||
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
@@ -28,6 +35,7 @@ import io.reactivex.android.schedulers.AndroidSchedulers;
|
|||||||
* Created by Stardust on 2017/9/28.
|
* Created by Stardust on 2017/9/28.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@SuppressLint("CheckResult")
|
||||||
public class EditorMenu {
|
public class EditorMenu {
|
||||||
|
|
||||||
private EditorView mEditorView;
|
private EditorView mEditorView;
|
||||||
@@ -112,6 +120,9 @@ public class EditorMenu {
|
|||||||
case R.id.action_console:
|
case R.id.action_console:
|
||||||
showConsole();
|
showConsole();
|
||||||
return true;
|
return true;
|
||||||
|
case R.id.action_import_java_class:
|
||||||
|
importJavaPackageOrClass();
|
||||||
|
return true;
|
||||||
case R.id.action_editor_text_size:
|
case R.id.action_editor_text_size:
|
||||||
mEditorView.selectTextSize();
|
mEditorView.selectTextSize();
|
||||||
return true;
|
return true;
|
||||||
@@ -132,6 +143,52 @@ public class EditorMenu {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void importJavaPackageOrClass() {
|
||||||
|
mEditor.getSelection()
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(s ->
|
||||||
|
new ClassSearchDialogBuilder(mContext)
|
||||||
|
.setQuery(s)
|
||||||
|
.itemClick((dialog, item, pos) -> showClassSearchingItem(dialog, item))
|
||||||
|
.title(R.string.text_search_java_class)
|
||||||
|
.show()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showClassSearchingItem(MaterialDialog dialog, ClassSearchingItem item) {
|
||||||
|
String title;
|
||||||
|
String desc;
|
||||||
|
if (item instanceof ClassSearchingItem.ClassItem) {
|
||||||
|
AndroidClass androidClass = ((ClassSearchingItem.ClassItem) item).getAndroidClass();
|
||||||
|
title = androidClass.getClassName();
|
||||||
|
desc = androidClass.getFullName();
|
||||||
|
} else {
|
||||||
|
title = ((ClassSearchingItem.PackageItem) item).getPackageName();
|
||||||
|
desc = title;
|
||||||
|
}
|
||||||
|
new ThemeColorMaterialDialogBuilder(mContext)
|
||||||
|
.title(title)
|
||||||
|
.content(desc)
|
||||||
|
.positiveText(R.string.text_copy)
|
||||||
|
.negativeText(R.string.text_en_import)
|
||||||
|
.neutralText(R.string.text_view_docs)
|
||||||
|
.onPositive((ignored, which) -> {
|
||||||
|
ClipboardUtil.setClip(mContext, desc);
|
||||||
|
Toast.makeText(mContext, R.string.text_already_copy_to_clip, Toast.LENGTH_SHORT).show();
|
||||||
|
dialog.dismiss();
|
||||||
|
})
|
||||||
|
.onNegative((ignored, which) -> {
|
||||||
|
if (mEditor.getText().startsWith(JavaScriptSource.EXECUTION_MODE_UI_PREFIX)) {
|
||||||
|
mEditor.insert(1, item.getImportText() + ";\n");
|
||||||
|
} else {
|
||||||
|
mEditor.insert(0, item.getImportText() + ";\n");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.onNeutral((ignored, which) -> IntentUtil.browse(mContext, item.getUrl()))
|
||||||
|
.onAny((ignored, which) -> dialog.dismiss())
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
private void startBuildApkActivity() {
|
private void startBuildApkActivity() {
|
||||||
BuildActivity_.intent(mContext)
|
BuildActivity_.intent(mContext)
|
||||||
.extra(BuildActivity.EXTRA_SOURCE_FILE, mEditorView.getFile().getPath())
|
.extra(BuildActivity.EXTRA_SOURCE_FILE, mEditorView.getFile().getPath())
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ public class CodeEditText extends AppCompatEditText {
|
|||||||
protected HVScrollView mParentScrollView;
|
protected HVScrollView mParentScrollView;
|
||||||
|
|
||||||
private final CopyOnWriteArrayList<CodeEditor.CursorChangeCallback> mCursorChangeCallbacks = new CopyOnWriteArrayList<>();
|
private final CopyOnWriteArrayList<CodeEditor.CursorChangeCallback> mCursorChangeCallbacks = new CopyOnWriteArrayList<>();
|
||||||
private volatile JavaScriptHighlighter.HighlightTokens mHighlightTokens;
|
private JavaScriptHighlighter.HighlightTokens mHighlightTokens;
|
||||||
private Theme mTheme;
|
private Theme mTheme;
|
||||||
private TimingLogger mLogger = new TimingLogger(LOG_TAG, "draw");
|
private TimingLogger mLogger = new TimingLogger(LOG_TAG, "draw");
|
||||||
private Paint mLineHighlightPaint = new Paint();
|
private Paint mLineHighlightPaint = new Paint();
|
||||||
@@ -195,7 +195,7 @@ public class CodeEditText extends AppCompatEditText {
|
|||||||
Layout layout = getLayout();
|
Layout layout = getLayout();
|
||||||
int lineCount = getLineCount();
|
int lineCount = getLineCount();
|
||||||
int textLength = highlightTokens == null ? 0 : highlightTokens.getText().length();
|
int textLength = highlightTokens == null ? 0 : highlightTokens.getText().length();
|
||||||
Editable text = getText();
|
String text = highlightTokens == null ? "" : highlightTokens.getText();
|
||||||
int paddingLeft = getPaddingLeft();
|
int paddingLeft = getPaddingLeft();
|
||||||
int scrollX = Math.max(getRealScrollX() - paddingLeft, 0);
|
int scrollX = Math.max(getRealScrollX() - paddingLeft, 0);
|
||||||
Paint paint = getPaint();
|
Paint paint = getPaint();
|
||||||
@@ -260,6 +260,12 @@ public class CodeEditText extends AppCompatEditText {
|
|||||||
}
|
}
|
||||||
paint.setColor(previousColor);
|
paint.setColor(previousColor);
|
||||||
float offsetX = paint.measureText(text, lineStart, previousColorPos);
|
float offsetX = paint.measureText(text, lineStart, previousColorPos);
|
||||||
|
if(previousColorPos < 0 || visibleCharEnd > textLength || previousColorPos >= visibleCharEnd){
|
||||||
|
Log.e(LOG_TAG, "IndexOutOfBounds: previousColorPos = " + previousColorPos + ", visibleCharEnd = "
|
||||||
|
+visibleCharEnd + ", textLength = " + textLength);
|
||||||
|
postInvalidate();
|
||||||
|
return;
|
||||||
|
}
|
||||||
canvas.drawText(text, previousColorPos, visibleCharEnd, paddingLeft + offsetX, lineBaseline, paint);
|
canvas.drawText(text, previousColorPos, visibleCharEnd, paddingLeft + offsetX, lineBaseline, paint);
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
mLogger.addSplit("draw line " + line + " (" + (visibleCharEnd - visibleCharStart) + ") ");
|
mLogger.addSplit("draw line " + line + " (" + (visibleCharEnd - visibleCharStart) + ") ");
|
||||||
@@ -407,8 +413,10 @@ public class CodeEditText extends AppCompatEditText {
|
|||||||
|
|
||||||
|
|
||||||
public void updateHighlightTokens(JavaScriptHighlighter.HighlightTokens highlightTokens) {
|
public void updateHighlightTokens(JavaScriptHighlighter.HighlightTokens highlightTokens) {
|
||||||
mHighlightTokens = highlightTokens;
|
post(() -> {
|
||||||
postInvalidate();
|
mHighlightTokens = highlightTokens;
|
||||||
|
invalidate();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -317,6 +317,11 @@ public class CodeEditor extends HVScrollView {
|
|||||||
mCodeEditText.getText().insert(selection, insertText);
|
mCodeEditText.getText().insert(selection, insertText);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void insert(int line, String insertText) {
|
||||||
|
int selection = mCodeEditText.getLayout().getLineStart(line);
|
||||||
|
mCodeEditText.getText().insert(selection, insertText);
|
||||||
|
}
|
||||||
|
|
||||||
public void moveCursor(int dCh) {
|
public void moveCursor(int dCh) {
|
||||||
mCodeEditText.setSelection(mCodeEditText.getSelectionStart() + dCh);
|
mCodeEditText.setSelection(mCodeEditText.getSelectionStart() + dCh);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package org.autojs.autojs.ui.main;
|
package org.autojs.autojs.ui.main;
|
||||||
|
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
@@ -14,6 +15,7 @@ import android.support.v4.view.ViewPager;
|
|||||||
import android.support.v4.widget.DrawerLayout;
|
import android.support.v4.widget.DrawerLayout;
|
||||||
import android.support.v7.app.ActionBarDrawerToggle;
|
import android.support.v7.app.ActionBarDrawerToggle;
|
||||||
import android.support.v7.widget.Toolbar;
|
import android.support.v7.widget.Toolbar;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
@@ -32,6 +34,7 @@ import org.autojs.autojs.BuildConfig;
|
|||||||
import org.autojs.autojs.Pref;
|
import org.autojs.autojs.Pref;
|
||||||
import org.autojs.autojs.R;
|
import org.autojs.autojs.R;
|
||||||
import org.autojs.autojs.autojs.AutoJs;
|
import org.autojs.autojs.autojs.AutoJs;
|
||||||
|
import org.autojs.autojs.model.indices.AndroidClassIndices;
|
||||||
import org.autojs.autojs.storage.file.StorageFileProvider;
|
import org.autojs.autojs.storage.file.StorageFileProvider;
|
||||||
import org.autojs.autojs.timing.TimedTaskManager;
|
import org.autojs.autojs.timing.TimedTaskManager;
|
||||||
import org.autojs.autojs.tool.AccessibilityServiceTool;
|
import org.autojs.autojs.tool.AccessibilityServiceTool;
|
||||||
@@ -68,6 +71,8 @@ import org.opencv.core.Core;
|
|||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
|
|
||||||
@EActivity(R.layout.activity_main)
|
@EActivity(R.layout.activity_main)
|
||||||
public class MainActivity extends BaseActivity implements OnActivityResultDelegate.DelegateHost, BackPressedHandler.HostActivity, PermissionRequestProxyActivity {
|
public class MainActivity extends BaseActivity implements OnActivityResultDelegate.DelegateHost, BackPressedHandler.HostActivity, PermissionRequestProxyActivity {
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package org.autojs.autojs.ui.widget;
|
|||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import org.autojs.autojs.model.indices.ClassSearchingItem;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -76,4 +78,15 @@ public class AutoAdapter<DT> extends RecyclerView.Adapter<BindableViewHolder<DT>
|
|||||||
public List<DT> getData() {
|
public List<DT> getData() {
|
||||||
return mData;
|
return mData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void removeAll() {
|
||||||
|
mData.clear();
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void notifyDataSetChanged(List<DT> result) {
|
||||||
|
mData.clear();
|
||||||
|
mData.addAll(result);
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
35
app/src/main/res/layout/dialog_class_search.xml
Normal file
35
app/src/main/res/layout/dialog_class_search.xml
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<android.support.design.widget.TextInputLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<android.support.design.widget.TextInputEditText
|
||||||
|
android:id="@+id/keywords"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="@string/text_class_or_package_name"/>
|
||||||
|
</android.support.design.widget.TextInputLayout>
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<android.support.v7.widget.RecyclerView
|
||||||
|
android:id="@+id/result_list"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="400dp"/>
|
||||||
|
|
||||||
|
<me.zhanghai.android.materialprogressbar.MaterialProgressBar
|
||||||
|
android:id="@+id/progress_bar"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:visibility="gone"/>
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
|
</LinearLayout>
|
||||||
21
app/src/main/res/layout/item_class_searching_result_list.xml
Normal file
21
app/src/main/res/layout/item_class_searching_result_list.xml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:paddingBottom="10dp"
|
||||||
|
android:background="?selectableItemBackground"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true"
|
||||||
|
android:paddingLeft="6dp"
|
||||||
|
android:paddingRight="6dp"
|
||||||
|
android:paddingTop="10dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/label"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:textColor="#B2B3B7"
|
||||||
|
android:textSize="15sp"/>
|
||||||
|
</LinearLayout>
|
||||||
@@ -119,6 +119,12 @@
|
|||||||
android:id="@+id/action_console"
|
android:id="@+id/action_console"
|
||||||
android:title="@string/text_console"
|
android:title="@string/text_console"
|
||||||
app:showAsAction="never"/>
|
app:showAsAction="never"/>
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_import_java_class"
|
||||||
|
android:title="@string/text_search_java_class"
|
||||||
|
app:showAsAction="never"/>
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_info"
|
android:id="@+id/action_info"
|
||||||
android:title="@string/text_info"
|
android:title="@string/text_info"
|
||||||
|
|||||||
@@ -383,4 +383,8 @@
|
|||||||
<string name="error_connect_to_remote">连接失败: %s</string>
|
<string name="error_connect_to_remote">连接失败: %s</string>
|
||||||
<string name="text_are_you_sure_to_delete">确定要删除%s吗</string>
|
<string name="text_are_you_sure_to_delete">确定要删除%s吗</string>
|
||||||
<string name="text_run_on_boot">开机时运行</string>
|
<string name="text_run_on_boot">开机时运行</string>
|
||||||
|
<string name="text_search_java_class">搜索Java包/类</string>
|
||||||
|
<string name="text_class_or_package_name">类/包名</string>
|
||||||
|
<string name="text_view_docs">查看文档</string>
|
||||||
|
<string name="text_en_import">import</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ public abstract class JavaScriptSource extends ScriptSource {
|
|||||||
|
|
||||||
public static final String ENGINE = "com.stardust.autojs.script.JavaScriptSource.Engine";
|
public static final String ENGINE = "com.stardust.autojs.script.JavaScriptSource.Engine";
|
||||||
|
|
||||||
|
public static final String EXECUTION_MODE_UI_PREFIX = "\"ui\";";
|
||||||
|
|
||||||
public static final int EXECUTION_MODE_NORMAL = 0;
|
public static final int EXECUTION_MODE_NORMAL = 0;
|
||||||
public static final int EXECUTION_MODE_UI = 0x00000001;
|
public static final int EXECUTION_MODE_UI = 0x00000001;
|
||||||
public static final int EXECUTION_MODE_AUTO = 0x00000002;
|
public static final int EXECUTION_MODE_AUTO = 0x00000002;
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":413},"path":"commonRelease-4.0.2 Alpha8.apk","properties":{"packageId":"org.autojs.autojs","split":"","minSdkVersion":"17"}}]
|
[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":414},"path":"commonRelease-4.0.2 Alpha9.apk","properties":{"packageId":"org.autojs.autojs","split":"","minSdkVersion":"17"}}]
|
||||||
Reference in New Issue
Block a user