Commit Test

This commit is contained in:
hyb1996 2017-04-29 21:23:45 +08:00
parent 6829c0659e
commit 51349356a7
65 changed files with 758 additions and 1751 deletions

View File

@ -76,6 +76,7 @@ dependencies {
compile group:'com.twofortyfouram', name:'android-plugin-client-sdk-for-locale', version:'[4.0.2, 5.0['
compile 'com.android.volley:volley:1.0.0'
compile 'com.github.hyb1996:EnhancedFloaty:0.11'
compile 'com.android.support:multidex:1.0.1'
compile(name: 'libtermexec-release', ext: 'aar')
compile(name: 'emulatorview-release', ext: 'aar')
compile(name: 'term-debug', ext: 'aar')

View File

@ -77,13 +77,13 @@
<activity android:name=".ui.error.ErrorReportActivity"/>
<activity android:name=".ui.help.LocalWebViewActivity"/>
<activity android:name=".external.tasker.TaskerScriptEditActivity"/>
<activity android:name=".ui.edit.ViewSampleActivity"/>
<activity
android:name=".ui.error.IssueReporterActivity"
android:theme="@style/IssueReporterTheme"/>
<service android:name="com.stardust.view.Floaty$FloatHeadService"/>
<service android:name="com.stardust.view.ResizableFloaty$FloatingWindowService"/>
<service android:name="com.stardust.scriptdroid.external.floating_window.HoverMenuService"/>
<activity android:name=".external.tasker.TaskPrefEditActivity"/>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

View File

@ -1,29 +0,0 @@
importClass(com.stardust.mi666.Cracker);
var cracker = new Cracker();
const path = "/sdcard/666.png";
var count = 1;
sleep(2000);
while(notStopped()){
Screencap(path);
sleep(2000);
toast("你已经被耍了" + count + "次");
var coords = cracker.crack(path);
for each(var coord in coords){
Tap(coord[0], coord[1]);
}
sleep(9000);
关闭();
sleep(2000);
console.log(++count);
再玩一次();
sleep(10000);
}
function 关闭(){
Tap(933, 660);
}
function 再玩一次(){
Tap(521, 1615);
}

View File

@ -16,6 +16,10 @@ import java.util.List;
public class FragmentPagerAdapterBuilder {
public interface OnFragmentInstantiateListener {
void OnInstantiate(Fragment fragment);
}
private List<Fragment> mFragments = new ArrayList<>();
private List<String> mTitles = new ArrayList<>();
private FragmentActivity mActivity;
@ -56,6 +60,7 @@ public class FragmentPagerAdapterBuilder {
public abstract static class StoredFragmentPagerAdapter extends FragmentPagerAdapter {
private SparseArray<Fragment> mStoredFragments = new SparseArray<>();
private OnFragmentInstantiateListener mOnFragmentInstantiateListener;
public StoredFragmentPagerAdapter(FragmentManager fm) {
super(fm);
@ -65,9 +70,13 @@ public class FragmentPagerAdapterBuilder {
public Object instantiateItem(ViewGroup container, int position) {
Fragment fragment = (Fragment) super.instantiateItem(container, position);
mStoredFragments.put(position, fragment);
if(mOnFragmentInstantiateListener != null){
mOnFragmentInstantiateListener.OnInstantiate(fragment);
}
return fragment;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
mStoredFragments.remove(position);
@ -77,5 +86,9 @@ public class FragmentPagerAdapterBuilder {
public Fragment getStoredFragment(int position) {
return mStoredFragments.get(position);
}
public void setOnFragmentInstantiateListener(OnFragmentInstantiateListener onFragmentInstantiateListener) {
mOnFragmentInstantiateListener = onFragmentInstantiateListener;
}
}
}

View File

@ -1,68 +0,0 @@
package com.stardust.mi666;
import com.stardust.util.ScreenMetrics;
import java.util.List;
/**
* Created by Stardust on 2017/4/24.
*/
public class Cracker {
private OCR mOCR;
private Solver mSolver;
private int mX, mY, mIntervalX, mIntervalY, mWidth, mHeight;
private void init(int x, int y, int intervalX, int intervalY, int w, int h) {
mOCR = new OCR(x, y, intervalX, intervalY, w, h);
mSolver = new Solver();
mX = x;
mY = y;
mIntervalY = intervalY;
mIntervalX = intervalX;
mWidth = w;
mHeight = h;
}
public Cracker() {
if (ScreenMetrics.getScreenWidth() == 1080 && ScreenMetrics.getScreenHeight() == 1920) {
init(68, 724, 238, 236, 228, 68);
} else {
double scaleX = 1080 / ScreenMetrics.getScreenWidth();
double scaleY = 1920 / ScreenMetrics.getScreenHeight();
init((int) (68 * scaleX), (int) (724 * scaleY), (int) (238 * scaleX), (int) (236 * scaleY), (int) (228 * scaleX), (int) (68 * scaleY));
}
}
public int[][] crack(String path) {
List<Integer> numbers = mOCR.detect(path);
mSolver.solve(numbers);
if (!mSolver.isSolved()) {
return new int[0][];
}
List<Integer> result = mSolver.getResult();
boolean[] used = new boolean[numbers.size()];
int[][] coordinates = new int[result.size()][2];
for (int i = 0; i < coordinates.length; i++) {
int index = indexOf(numbers, used, result.get(i));
int row = index / 4;
int col = index % 4;
int x = mX + mIntervalX * col + mWidth / 2;
int y = mY + mIntervalY * row + mHeight / 2;
coordinates[i][0] = x;
coordinates[i][1] = y;
}
return coordinates;
}
private int indexOf(List<Integer> numbers, boolean[] used, int integer) {
for (int i = 0; i < numbers.size(); i++) {
if (numbers.get(i) == integer && !used[i]) {
used[i] = true;
return i;
}
}
return -1;
}
}

View File

@ -1,81 +0,0 @@
package com.stardust.mi666;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;
import com.stardust.mi666.ocr.ColorDetector;
import com.stardust.mi666.ocr.SimpleTextSplitter;
import com.stardust.mi666.ocr.TemplateMatching;
import com.stardust.pio.UncheckedIOException;
import com.stardust.util.ViewUtil;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Stardust on 2017/4/24.
*/
public class OCR {
private static com.stardust.mi666.ocr.OCR ocr;
private static SimpleTextSplitter textSplitter;
static {
ColorDetector colorDetector = new ColorDetector.SimpleColorDetector(0xff9f826f);
ocr = new TemplateMatching.TemplateMatchingOCR(1, colorDetector);
textSplitter = new SimpleTextSplitter(colorDetector);
}
private int mX, mY, mIntervalX, mIntervalY, mWidth, mHeight;
public OCR(int x, int y, int intervalX, int intervalY, int w, int h) {
mX = x;
mY = y;
mIntervalY = intervalY;
mIntervalX = intervalX;
mWidth = w;
mHeight = h;
}
public static void init(Context context) {
try {
for (int i = 0; i < 10; i++) {
Bitmap number = BitmapFactory.decodeStream(context.getAssets().open("numbers/" + i + ".png"));
ocr.addChar((char) ('0' + i), number);
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public List<Integer> detect(String path) {
Bitmap screenshot = BitmapFactory.decodeFile(path);
try {
List<Integer> numbers = new ArrayList<>(16);
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
Bitmap block = getBlockAt(screenshot, i, j);
List<Bitmap> bitmaps = textSplitter.split(block);
StringBuilder sb = new StringBuilder();
for (Bitmap num : bitmaps) {
sb.append(ocr.detect(num));
}
numbers.add(Integer.parseInt(sb.toString()));
Log.i("TestOCR", "result = " + sb);
}
}
return numbers;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private Bitmap getBlockAt(Bitmap bitmap, int row, int col) {
return Bitmap.createBitmap(bitmap, mX + col * mIntervalX, mY + row * mIntervalY, mWidth, mHeight);
}
}

View File

@ -1,55 +0,0 @@
package com.stardust.mi666;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Stardust on 2017/4/24.
*/
public class Solver {
private boolean mSolved = false;
private List<Integer> mResult = new ArrayList<>();
private List<Integer> mTmpList = new ArrayList<>();
private int[] value;
void solve(int sum, int index) {
if (mSolved || index < 0) return;
if (sum == value[index] && mTmpList.size() == 5) {
mSolved = true;
mTmpList.add(value[index]);
mResult.addAll(mTmpList);
return;
}
mTmpList.add(value[index]);
solve(sum - value[index], index - 1);
mTmpList.remove(mTmpList.size() - 1);
solve(sum, index - 1);
}
public void solve(int[] num) {
mResult.clear();
mTmpList.clear();
mSolved = false;
value = num;
solve(6666, 15);
}
public boolean isSolved() {
return mSolved;
}
public List<Integer> getResult() {
return mResult;
}
public void solve(List<Integer> numbers) {
int[] num = new int[numbers.size()];
for (int i = 0; i < num.length; i++) {
num[i] = numbers.get(i);
}
solve(num);
}
}

View File

@ -1,53 +0,0 @@
package com.stardust.mi666.ocr;
import android.graphics.Color;
/**
* Created by Stardust on 2017/4/23.
*/
public interface ColorDetector {
boolean isCharPixel(int color);
class ColorDistanceDetector implements ColorDetector {
private int mColor;
private double mThreshold;
public ColorDistanceDetector(int color, double threshold) {
mColor = color;
mThreshold = threshold;
}
public static double distance(int c1, int c2) {
double meanR = (Color.red(c1) + Color.red(c2)) / 2;
int r = Color.red(c1) - Color.red(c2);
int g = Color.green(c1) - Color.green(c2);
int b = Color.blue(c1) - Color.blue(c2);
double weightR = 2 + meanR / 256;
double weightG = 4.0;
double weightB = 2 + (255 - meanR) / 256;
return Math.sqrt(weightR * r * r + weightG * g * g + weightB * b * b);
}
@Override
public boolean isCharPixel(int color) {
return distance(color, mColor) < mThreshold;
}
}
class SimpleColorDetector implements ColorDetector {
private int mColor;
public SimpleColorDetector(int color) {
mColor = color;
}
@Override
public boolean isCharPixel(int color) {
return mColor == color;
}
}
}

View File

@ -1,15 +0,0 @@
package com.stardust.mi666.ocr;
import android.graphics.Bitmap;
/**
* Created by Stardust on 2017/4/23.
*/
public interface OCR {
void addChar(char ch, Bitmap bitmap);
char detect(Bitmap bitmap);
}

View File

@ -1,142 +0,0 @@
package com.stardust.mi666.ocr;
import android.graphics.Bitmap;
import android.util.Log;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Created by Stardust on 2017/4/23.
*/
public class SimpleOCR implements OCR {
private static class PixelLine {
int start;
int end;
PixelLine(int start, int end) {
this.start = start;
this.end = end;
}
}
private static class PixelLines {
int start = -1;
List<PixelLine> lines = new ArrayList<>();
void addLine(PixelLine line) {
lines.add(line);
if (start == -1 || start > line.start) {
start = line.start;
}
}
int distanceTo(PixelLines another) {
if (lines.size() != another.lines.size()) {
return lineWidthSum() + another.lineWidthSum();
}
int offset = another.start - start;
int sum = 0;
for (int i = 0; i < lines.size(); i++) {
sum += Math.abs(lines.get(i).start + offset - another.lines.get(i).start);
sum += Math.abs(lines.get(i).end + offset - another.lines.get(i).end);
}
return sum;
}
private int lineWidthSum() {
int sum = 0;
for (PixelLine line : lines) {
sum += line.end - line.start;
}
return sum;
}
}
public static class CharFeature {
private List<PixelLines> mPixelLinesPerRow;
public CharFeature(int rowNumber) {
mPixelLinesPerRow = new ArrayList<>(rowNumber);
for (int i = 0; i < rowNumber; i++) {
mPixelLinesPerRow.add(new PixelLines());
}
}
void addLine(int row, PixelLine line) {
mPixelLinesPerRow.get(row).addLine(line);
}
int distanceTo(CharFeature feature) {
int sum = 0;
if (feature.mPixelLinesPerRow.size() != mPixelLinesPerRow.size()) {
for (PixelLines lines : mPixelLinesPerRow) {
sum += lines.lines.size();
}
return sum;
}
for (int i = 0; i < mPixelLinesPerRow.size(); i++) {
sum += mPixelLinesPerRow.get(i).distanceTo(feature.mPixelLinesPerRow.get(i));
}
return sum;
}
}
private static final String TAG = "SimpleOCR";
private Map<Character, CharFeature> mChars = new HashMap<>();
private ColorDetector mColorDetector;
public SimpleOCR(ColorDetector colorDetector) {
mColorDetector = colorDetector;
}
public void addChar(char c, Bitmap ch) {
mChars.put(c, getCharFeature(ch));
}
public CharFeature getCharFeature(Bitmap bitmap) {
CharFeature feature = new CharFeature(bitmap.getHeight());
for (int y = 0; y < bitmap.getHeight(); y++) {
int mPixelStart = -1;
for (int x = 0; x < bitmap.getWidth(); x++) {
if (mColorDetector.isCharPixel(bitmap.getPixel(x, y))) {
if (mPixelStart == -1) {
mPixelStart = x;
}
} else if (mPixelStart >= 0) {
feature.addLine(y, new PixelLine(mPixelStart, x));
mPixelStart = -1;
}
}
if (mPixelStart >= 0) {
feature.addLine(y, new PixelLine(mPixelStart, bitmap.getWidth()));
}
}
return feature;
}
public char detect(Bitmap bitmap) {
CharFeature feature = getCharFeature(bitmap);
int min = Integer.MAX_VALUE;
char detectedChar = ' ';
for (Map.Entry<Character, CharFeature> ch : mChars.entrySet()) {
int distance = ch.getValue().distanceTo(feature);
Log.d(TAG, "ch=" + ch.getKey() + " distance=" + distance);
if (distance < min) {
min = distance;
detectedChar = ch.getKey();
}
}
return detectedChar;
}
}

View File

@ -1,34 +0,0 @@
package com.stardust.mi666.ocr;
import android.graphics.Bitmap;
/**
* Created by Stardust on 2017/4/23.
*/
public class SimpleTextDetector {
private ColorDetector mColorDetector;
public SimpleTextDetector(ColorDetector colorDetector) {
mColorDetector = colorDetector;
}
public Bitmap detect(Bitmap bitmap) {
int minX = bitmap.getWidth();
int minY = bitmap.getHeight();
int maxX = 0;
int maxY = 0;
for (int i = 0; i < bitmap.getWidth(); i++) {
for (int j = 0; j < bitmap.getHeight(); j++) {
if (mColorDetector.isCharPixel(bitmap.getPixel(i, j))) {
minX = Math.min(minX, i);
minY = Math.min(minY, j);
maxX = Math.max(maxX, i);
maxY = Math.max(maxY, j);
}
}
}
return Bitmap.createBitmap(bitmap, minX, minY, maxX - minX, maxY - minY);
}
}

View File

@ -1,52 +0,0 @@
package com.stardust.mi666.ocr;
import android.graphics.Bitmap;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Stardust on 2017/4/24.
*/
public class SimpleTextSplitter {
private ColorDetector mColorDetector;
private SimpleTextDetector mSimpleTextDetector;
public SimpleTextSplitter(ColorDetector colorDetector) {
mColorDetector = colorDetector;
mSimpleTextDetector = new SimpleTextDetector(colorDetector);
}
public List<Bitmap> split(Bitmap bitmap) {
Bitmap text = mSimpleTextDetector.detect(bitmap);
int[] projection = new int[text.getWidth()];
for (int i = 0; i < text.getWidth(); i++) {
for (int j = 0; j < text.getHeight(); j++) {
if (mColorDetector.isCharPixel(text.getPixel(i, j))) {
projection[i]++;
}
}
}
int start = -1;
List<Bitmap> numbers = new ArrayList<>();
for (int i = 0; i < text.getWidth(); i++) {
if (projection[i] > 0) {
if (start == -1) {
start = i;
}
} else {
if (start >= 0) {
numbers.add(Bitmap.createBitmap(text, start, 0, i - start, text.getHeight()));
start = -1;
}
}
}
if (start >= 0) {
numbers.add(Bitmap.createBitmap(text, start, 0, text.getWidth() - start, text.getHeight()));
}
return numbers;
}
}

View File

@ -1,109 +0,0 @@
package com.stardust.mi666.ocr;
import android.graphics.Bitmap;
import android.util.Log;
import com.stardust.scriptdroid.tool.BitmapTool;
import java.util.HashMap;
import java.util.Map;
/**
* Created by Stardust on 2017/4/23.
*/
public class TemplateMatching {
private static final String LOG_TAG = "TemplateMatching";
private int mBlockSize;
private ColorDetector mColorDetector;
public TemplateMatching(int blockSize, ColorDetector colorDetector) {
mBlockSize = blockSize;
mColorDetector = colorDetector;
}
public int[][] getFeature(Bitmap bitmap) {
int w = bitmap.getWidth() / mBlockSize;
int h = bitmap.getHeight() / mBlockSize;
int[][] mat = new int[w][h];
for (int i = 0; i < bitmap.getWidth(); i++) {
for (int j = 0; j < bitmap.getHeight(); j++) {
if (mColorDetector.isCharPixel(bitmap.getPixel(i, j))) {
mat[i * w / bitmap.getWidth()][j * h / bitmap.getHeight()]++;
}
}
}
return mat;
}
public int distance(int[][] f, int[][] template, int offsetX, int offsetY) {
int sum = 0;
for (int i = 0; i < template.length; i++) {
for (int j = 0; j < template[i].length; j++) {
if (i >= f.length || j >= f[i].length) {
sum += template[i].length - j;
break;
}
sum += Math.abs(template[i][j] - f[i + offsetX][j + offsetY]);
}
}
return sum;
}
public int minDistance(int[][] f, int[][] template) {
int min = Integer.MAX_VALUE;
int i = 0;
while (i < template.length && i + template.length - 1 < f.length) {
int j = 0;
while (j < template[i].length && j + template[i].length - 1 < f[i].length) {
int d = distance(f, template, i, j);
if (d < min) {
min = d;
}
j++;
}
i++;
}
return min;
}
public static class TemplateMatchingOCR implements OCR {
private Map<Character, int[][]> mChars = new HashMap<>();
private TemplateMatching mTemplateMatching;
private SimpleTextDetector mSimpleTextDetector;
public TemplateMatchingOCR(int blockSize, ColorDetector colorDetector) {
mTemplateMatching = new TemplateMatching(blockSize, colorDetector);
mSimpleTextDetector = new SimpleTextDetector(colorDetector);
}
@Override
public void addChar(char ch, Bitmap bitmap) {
mChars.put(ch, mTemplateMatching.getFeature(mSimpleTextDetector.detect(bitmap)));
}
@Override
public char detect(Bitmap bitmap) {
int min = Integer.MAX_VALUE;
char ch = ' ';
for (Map.Entry<Character, int[][]> entry : mChars.entrySet()) {
int[][] f = mTemplateMatching.getFeature(BitmapTool.scaleBitmap(bitmap, entry.getValue().length, entry.getValue()[0].length));
int d = mTemplateMatching.distance(f, entry.getValue(), 0, 0);
Log.d(LOG_TAG, "char: " + entry.getKey() + " distance: " + d);
if (d < min) {
if (entry.getKey() == '1' && d > 30) {
continue;
}
min = d;
ch = entry.getKey();
}
}
return ch;
}
}
}

View File

@ -1,16 +1,14 @@
package com.stardust.scriptdroid;
import android.app.Activity;
import android.app.Application;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.annotation.Keep;
import android.support.multidex.MultiDexApplication;
import com.squareup.leakcanary.LeakCanary;
import com.stardust.app.SimpleActivityLifecycleCallbacks;
import com.stardust.app.VolumeChangeObserver;
import com.stardust.mi666.OCR;
import com.stardust.scriptdroid.autojs.AutoJs;
import com.stardust.scriptdroid.service.AccessibilityWatchDogService;
import com.stardust.scriptdroid.tool.CrashHandler;
@ -26,7 +24,7 @@ import java.lang.ref.WeakReference;
* Created by Stardust on 2017/1/27.
*/
public class App extends Application {
public class App extends MultiDexApplication {
private static final String TAG = "App";
@ -65,7 +63,6 @@ public class App extends Application {
JsBeautifierFactory.initJsBeautify(this, "js/jsbeautify.js");
initVolumeChangeObserver();
startService(new Intent(this, AccessibilityWatchDogService.class));
OCR.init(this);
}
private void initVolumeChangeObserver() {
@ -94,7 +91,6 @@ public class App extends Application {
currentActivity = new WeakReference<>(activity);
}
});
}

View File

@ -4,6 +4,7 @@ import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import com.stardust.autojs.runtime.api.AutomatorConfig;
import com.stardust.automator.AccessibilityEventCommandHost;
import com.stardust.scriptdroid.autojs.AutoJs;
@ -18,11 +19,19 @@ public class Pref {
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (key.equals(getString(R.string.key_run_mode))) {
AutoJs.getInstance().getCommandHost().setRunMode(getRunModeFromValue(sharedPreferences.getString(key, null)));
} else if (key.equals(getString(R.string.key_guard_mode))) {
AutomatorConfig.setIsUnintendedGuardEnabled(sharedPreferences.getBoolean(getString(R.string.key_guard_mode), false));
}
}
};
static {
AutomatorConfig.setIsUnintendedGuardEnabled(def().getBoolean(getString(R.string.key_guard_mode), false));
}
private static int getRunModeFromValue(String value) {
if (value == null)
return AccessibilityEventCommandHost.RUN_MODE_THREAD_POOL;
switch (value) {
case "KEY_THREAD_POOL":
return AccessibilityEventCommandHost.RUN_MODE_THREAD_POOL;

View File

@ -15,7 +15,6 @@ import com.stardust.scriptdroid.scripts.ScriptFile;
import com.stardust.scriptdroid.scripts.StorageScriptProvider;
import com.stardust.scriptdroid.ui.edit.EditActivity;
import com.stardust.scriptdroid.ui.main.script_list.ScriptAndFolderListRecyclerView;
import com.stardust.scriptdroid.ui.main.script_list.ScriptListRecyclerView;
import com.stardust.scriptdroid.ui.main.script_list.ScriptListWithProgressBarView;
import com.stardust.util.MessageEvent;
import com.stardust.widget.ViewHolderSupplier;

View File

@ -37,7 +37,6 @@ public class FloatingLayoutBoundsView extends LayoutBoundsView {
showNodeInfo(info);
}
});
setBackgroundColor(0x66000000);
setVisibility(GONE);
getPaint().setColor(0xFF222222);
getPaint().setStrokeWidth(2f);

View File

@ -1,205 +0,0 @@
package com.stardust.scriptdroid.external.floating_window.view;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.TextView;
import android.widget.Toast;
import android.workground.WrapContentLinearLayoutManager;
import com.afollestad.materialdialogs.MaterialDialog;
import com.stardust.scriptdroid.scripts.ScriptFile;
import com.stardust.scriptdroid.scripts.ScriptFileList;
import com.stardust.scriptdroid.App;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.external.floating_window.HoverMenuService;
import com.stardust.util.ViewUtil;
import com.stardust.scriptdroid.ui.main.operation.ScriptFileOperation;
import com.stardust.scriptdroid.ui.main.operation.ScriptFileOperationPopupMenu;
import com.stardust.theme.dialog.ThemeColorMaterialDialogBuilder;
import com.stardust.util.MessageEvent;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Stardust on 2017/3/12.
*/
public class FloatingScriptFileListView extends RecyclerView {
private ScriptFileList mScriptFileList;
private final OnClickListener mOnItemClickListener = new OnClickListener() {
@Override
public void onClick(View v) {
int position = getChildViewHolder(v).getAdapterPosition();
onItemClicked(v, position);
}
};
private final OnClickListener mOnEditIconClickListener = new OnClickListener() {
@Override
public void onClick(View v) {
int position = getChildViewHolder((View) v.getParent()).getAdapterPosition();
onEditIconClick(v, position);
}
};
private final OnClickListener mOnMoreIconClickListener = new OnClickListener() {
@Override
public void onClick(View v) {
mOperateFileIndex = getChildViewHolder((View) v.getParent()).getAdapterPosition();
showOrDismissOperationPopupMenu(v);
}
};
private ScriptFileOperationPopupMenu mScriptFileOperationPopupMenu;
private int mOperateFileIndex;
public FloatingScriptFileListView(Context context) {
super(context);
init();
}
private void init() {
setAdapter(new Adapter());
setLayoutManager(new WrapContentLinearLayoutManager(getContext()));
addItemDecoration(new DividerItemDecoration(getContext(), DividerItemDecoration.VERTICAL));
initScriptFileOperationPopupMenu();
}
@Subscribe
public void showMessage(ScriptFileOperation.ShowMessageEvent event) {
Toast.makeText(getContext(), event.messageResId, Toast.LENGTH_SHORT).show();
}
private void initScriptFileOperationPopupMenu() {
mScriptFileOperationPopupMenu = new ScriptFileOperationPopupMenu(getContext(), getScriptFileOperations());
mScriptFileOperationPopupMenu.setOnItemClickListener(new ScriptFileOperationPopupMenu.OnItemClickListener() {
@Override
public void onClick(View view, int position, ScriptFileOperation operation) {
operation.operate(FloatingScriptFileListView.this, mScriptFileList, mOperateFileIndex);
mScriptFileOperationPopupMenu.dismiss();
if (!(operation instanceof ScriptFileOperation.Rename))
EventBus.getDefault().post(new MessageEvent(HoverMenuService.MESSAGE_COLLAPSE_MENU));
}
});
}
protected List<ScriptFileOperation> getScriptFileOperations() {
List<ScriptFileOperation> scriptFileOperations = new ArrayList<>();
scriptFileOperations.add(new ScriptFileOperation.Run());
scriptFileOperations.add(new ScriptFileOperation.Rename() {
@Override
public void operate(final RecyclerView recyclerView, final ScriptFileList scriptFileList, final int position) {
String oldName = scriptFileList.get(position).getSimplifiedName();
MaterialDialog dialog = new ThemeColorMaterialDialogBuilder(recyclerView.getContext())
.title(R.string.text_rename)
.checkBoxPrompt(App.getApp().getString(R.string.text_rename_file_meanwhile), false, null)
.input(App.getApp().getString(R.string.text_please_input_new_name), oldName, new MaterialDialog.InputCallback() {
@Override
public void onInput(@NonNull MaterialDialog dialog, CharSequence input) {
scriptFileList.rename(position, input.toString(), dialog.isPromptCheckBoxChecked());
recyclerView.getAdapter().notifyItemChanged(position);
}
})
.build();
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
dialog.show();
}
});
scriptFileOperations.add(new ScriptFileOperation.OpenByOtherApp());
scriptFileOperations.add(new ScriptFileOperation.CreateShortcut());
scriptFileOperations.add(new ScriptFileOperation.Remove());
scriptFileOperations.add(new ScriptFileOperation.Delete());
return scriptFileOperations;
}
protected void onItemClicked(View v, int position) {
new ScriptFileOperation.Run().operate(this, mScriptFileList, position);
EventBus.getDefault().post(new MessageEvent(HoverMenuService.MESSAGE_COLLAPSE_MENU));
}
protected void onEditIconClick(View v, int position) {
new ScriptFileOperation.Edit().operate(this, mScriptFileList, position);
EventBus.getDefault().post(new MessageEvent(HoverMenuService.MESSAGE_COLLAPSE_MENU));
}
public void setScriptFileList(ScriptFileList scriptFileList) {
mScriptFileList = scriptFileList;
getAdapter().notifyDataSetChanged();
}
private void showOrDismissOperationPopupMenu(View v) {
if (mScriptFileOperationPopupMenu.isShowing()) {
mScriptFileOperationPopupMenu.dismiss();
} else {
mScriptFileOperationPopupMenu.show(v);
}
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
EventBus.getDefault().register(this);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
EventBus.getDefault().unregister(this);
}
@Subscribe
public void onMenuCollapsing(MessageEvent event) {
if (event.message.equals(HoverMenuService.MESSAGE_MENU_COLLAPSING) && mScriptFileOperationPopupMenu.isShowing()) {
mScriptFileOperationPopupMenu.dismiss();
}
}
private class Adapter extends RecyclerView.Adapter<ViewHolder> {
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(getContext()).inflate(R.layout.floating_script_list_recycler_view_file, parent, false);
return new ViewHolder(itemView);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
ScriptFile scriptFile = mScriptFileList.get(position);
holder.name.setText(scriptFile.getSimplifiedName());
holder.path.setText(scriptFile.getSimplifiedPath());
}
@Override
public int getItemCount() {
return mScriptFileList.size();
}
}
private class ViewHolder extends RecyclerView.ViewHolder {
TextView name, path;
ViewHolder(View itemView) {
super(itemView);
name = (TextView) itemView.findViewById(R.id.name);
path = (TextView) itemView.findViewById(R.id.path);
ViewUtil.$(itemView, R.id.edit).setOnClickListener(mOnEditIconClickListener);
//ViewUtil.$(itemView, R.id.more).setOnClickListener(mOnMoreIconClickListener);
itemView.setOnClickListener(mOnItemClickListener);
}
}
}

View File

@ -20,7 +20,7 @@ public class ImportIntentActivity extends BaseActivity {
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
handleIntent();
handleIntent(getIntent());
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(this, R.string.edit_and_run_handle_intent_error, Toast.LENGTH_LONG).show();
@ -28,8 +28,12 @@ public class ImportIntentActivity extends BaseActivity {
}
}
private void handleIntent() {
Intent intent = getIntent();
@Override
protected void onNewIntent(Intent intent) {
handleIntent(intent);
}
private void handleIntent(Intent intent) {
final String path = intent.getData().getPath();
if (!TextUtils.isEmpty(path))
MainActivity.importScriptFile(this, path);

View File

@ -15,6 +15,9 @@ import android.view.View;
import com.stardust.scriptdroid.layout_inspector.NodeInfo;
import com.stardust.util.ViewUtil;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Stardust on 2017/3/10.
*/
@ -109,13 +112,20 @@ public class LayoutBoundsView extends View {
}
}
private NodeInfo findNodeAt(NodeInfo node, int x, int y) {
private List<NodeInfo> findNodeAt(NodeInfo node, int x, int y) {
List<NodeInfo> list = null;
for (NodeInfo child : node.getChildren()) {
if (child != null && child.getBoundsInScreen().contains(x, y)) {
return findNodeAt(child, x, y);
if (list == null)
list = findNodeAt(child, x, y);
else
list.addAll(findNodeAt(child, x, y));
}
}
return node;
if (list == null)
list = new ArrayList<>();
list.add(node);
return list;
}
}

View File

@ -1,10 +1,12 @@
package com.stardust.scriptdroid.scripts.sample;
import java.io.Serializable;
/**
* Created by Stardust on 2017/3/13.
*/
public class Sample {
public class Sample implements Serializable {
public String name;
public String path;
@ -12,4 +14,5 @@ public class Sample {
this.name = name;
this.path = path;
}
}

View File

@ -1,162 +0,0 @@
package com.stardust.scriptdroid.tool;
/**
* Created by Stardust on 2017/4/23.
*/
import android.graphics.Bitmap;
import com.stardust.mi666.ocr.ColorDetector;
import com.stardust.mi666.ocr.SimpleTextDetector;
import java.util.HashMap;
import java.util.Map;
public class ImagePHash {
private static final String LOG_TAG = "ImagePHash";
private int width = 32;
private int height;
private int smallerWidth = 8;
private int smallerHeight;
public ImagePHash() {
this(32, 8);
}
public ImagePHash(int width, int smallerWidth) {
this(width, width, smallerWidth, smallerWidth);
}
public ImagePHash(int width, int height, int smallerWidth, int smallerHeight) {
this.width = width;
this.height = height;
this.smallerWidth = smallerWidth;
this.smallerHeight = smallerHeight;
initCoefficients();
}
public int distance(boolean[] s1, boolean[] s2) {
int counter = 0;
for (int k = 0; k < s1.length; k++) {
if (s1[k] != s2[k]) {
counter++;
}
}
return counter;
}
public boolean[] getHash(Bitmap img) {
double[][] vals = new double[width][height];
img = BitmapTool.scaleBitmap(img, width, height);
for (int x = 0; x < img.getWidth(); x++) {
for (int y = 0; y < img.getHeight(); y++) {
vals[x][y] = getBlue(img, x, y);
}
}
double[][] dctVals = applyDCT(vals);
double total = 0;
for (int x = 0; x < smallerWidth; x++) {
for (int y = 0; y < smallerHeight; y++) {
total += dctVals[x][y];
}
}
total -= dctVals[0][0];
double avg = total / (double) ((smallerWidth * smallerHeight) - 1);
boolean[] hash = new boolean[smallerWidth * smallerHeight];
int i = 0;
for (int x = 0; x < smallerWidth; x++) {
for (int y = 0; y < smallerHeight; y++) {
if (x != 0 && y != 0) {
hash[i++] = dctVals[x][y] > avg;
}
}
}
return hash;
}
private static int getBlue(Bitmap img, int x, int y) {
return img.getPixel(x, y) & 0xff;
}
private double[] c;
private double[] c2;
private void initCoefficients() {
c = new double[width];
c2 = new double[height];
for (int i = 1; i < width; i++) {
c[i] = 1;
}
for (int i = 1; i < height; i++) {
c2[i] = 1;
}
c[0] = 1 / Math.sqrt(2.0);
c2[0] = 1 / Math.sqrt(2.0);
}
private double[][] applyDCT(double[][] f) {
double[][] F = new double[width][height];
for (int u = 0; u < width; u++) {
for (int v = 0; v < height; v++) {
double sum = 0.0;
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
sum += Math.cos(((2 * i + 1) / (2.0 * width)) * u * Math.PI) * Math.cos(((2 * j + 1) / (2.0 * height)) * v * Math.PI) * (f[i][j]);
}
}
sum *= ((c[u] * c2[v]) / 4.0);
F[u][v] = sum;
}
}
return F;
}
public static class OCR implements com.stardust.mi666.ocr.OCR {
private SimpleTextDetector mSimpleTextDetector;
private Map<Character, boolean[]> mChars = new HashMap<>();
private ImagePHash mImagePHash;
public OCR(ColorDetector colorDetector, int size, int smallerSize) {
mSimpleTextDetector = new SimpleTextDetector(colorDetector);
mImagePHash = new ImagePHash(size, smallerSize);
}
public OCR(ColorDetector colorDetector, ImagePHash pHash) {
mSimpleTextDetector = new SimpleTextDetector(colorDetector);
mImagePHash = pHash;
}
@Override
public void addChar(char ch, Bitmap bitmap) {
mChars.put(ch, mImagePHash.getHash(mSimpleTextDetector.detect(bitmap)));
}
@Override
public char detect(Bitmap bitmap) {
bitmap = mSimpleTextDetector.detect(bitmap);
int min = Integer.MAX_VALUE;
boolean[] h = mImagePHash.getHash(bitmap);
char ch = ' ';
for (Map.Entry<Character, boolean[]> entry : mChars.entrySet()) {
int d = mImagePHash.distance(h, entry.getValue());
//Log.i(LOG_TAG, "char: " + entry.getKey() + " distance: " + d);
if (d < min) {
min = d;
ch = entry.getKey();
}
}
return ch;
}
}
}

View File

@ -22,19 +22,15 @@ import timber.log.Timber;
public class TimberConsole implements Console {
static {
try {
Timber.plant(new ConsoleTree.Builder()
.minPriority(Log.VERBOSE)
.verboseColor(0xff909090)
.debugColor(0xffc88b48)
.infoColor(0xffc9c9c9)
.warnColor(0xffa97db6)
.errorColor(0xffff534e)
.assertColor(0xffff5540)
.build());
} catch (Exception e) {
// FIXME: 2017/4/26 java.lang.NoClassDefFoundError: com.jraska.console.timber.ConsoleTree at android4.4
}
Timber.plant(new ConsoleTree.Builder()
.minPriority(Log.VERBOSE)
.verboseColor(0xff909090)
.debugColor(0xffc88b48)
.infoColor(0xffc9c9c9)
.warnColor(0xffa97db6)
.errorColor(0xffff534e)
.assertColor(0xffff5540)
.build());
}
@Override

View File

@ -1,6 +1,5 @@
package com.stardust.scriptdroid.ui.edit;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@ -14,51 +13,49 @@ import android.util.SparseArray;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.inputmethod.InputMethod;
import com.afollestad.materialdialogs.DialogAction;
import com.afollestad.materialdialogs.MaterialDialog;
import com.stardust.autojs.engine.JavaScriptEngine;
import com.stardust.autojs.ScriptExecutionListener;
import com.stardust.autojs.script.FileScriptSource;
import com.stardust.autojs.script.JsBeautifier;
import com.stardust.autojs.script.ScriptSource;
import com.stardust.autojs.script.StringScriptSource;
import com.stardust.enhancedfloaty.ResizableFloatyService;
import com.stardust.pio.PFile;
import com.stardust.scriptdroid.Pref;
import com.stardust.scriptdroid.autojs.AutoJs;
import com.stardust.scriptdroid.external.floating_window.FloatingConsole;
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.editor920.Editor920Activity;
import com.stardust.scriptdroid.ui.edit.editor920.Editor920Utils;
import com.stardust.scriptdroid.ui.edit.sidemenu.EditSideMenuFragment;
import com.stardust.scriptdroid.ui.edit.sidemenu.FunctionListRecyclerView;
import com.stardust.scriptdroid.ui.help.HelpCatalogueActivity;
import com.stardust.theme.dialog.ThemeColorMaterialDialogBuilder;
import com.stardust.util.SparseArrayEntries;
import com.stardust.view.ViewBinding;
import com.stardust.widget.ToolbarMenuItem;
import com.jecelyin.editor.v2.common.Command;
import com.jecelyin.editor.v2.common.SaveListener;
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.ScriptExecutionListener;
import com.stardust.autojs.engine.JavaScriptEngine;
import com.stardust.autojs.script.FileScriptSource;
import com.stardust.autojs.script.JsBeautifier;
import com.stardust.autojs.script.ScriptSource;
import com.stardust.autojs.script.StringScriptSource;
import com.stardust.scriptdroid.App;
import com.stardust.scriptdroid.Pref;
import com.stardust.scriptdroid.R;
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;
import com.stardust.scriptdroid.ui.help.HelpCatalogueActivity;
import com.stardust.scriptdroid.ui.main.operation.ScriptFileOperation;
import com.stardust.theme.ThemeColorManager;
import com.stardust.theme.dialog.ThemeColorMaterialDialogBuilder;
import com.stardust.util.SparseArrayEntries;
import com.stardust.view.ViewBinder;
import com.stardust.view.ViewBinding;
import com.stardust.widget.ToolbarMenuItem;
import java.io.File;
import timber.log.Timber;
import static com.stardust.scriptdroid.ui.main.operation.ScriptFileOperation.ACTION_ON_RUN_FINISHED;
import static com.stardust.scriptdroid.ui.main.operation.ScriptFileOperation.EXTRA_EXCEPTION_MESSAGE;
/**
* Created by Stardust on 2017/1/29.
*/
@ -94,43 +91,10 @@ public class EditActivity extends Editor920Activity {
public static final String EXTRA_CONTENT = "Still Love Eating 17.4.5";
private static final String ACTION_ON_RUN_FINISHED = "ACTION_ON_RUN_FINISHED";
private static final String EXTRA_EXCEPTION_MESSAGE = "EXTRA_EXCEPTION_MESSAGE";
private static final ScriptExecutionListener SCRIPT_EXECUTION_LISTENER = new ScriptExecutionListener() {
@Override
public void onStart(JavaScriptEngine engine, ScriptSource source) {
AutoJs.getInstance().getScriptEngineService().getDefaultListener().onStart(engine, source);
}
@Override
public void onSuccess(JavaScriptEngine engine, ScriptSource source, Object result) {
App.getApp().sendBroadcast(new Intent(ACTION_ON_RUN_FINISHED));
}
@Override
public void onException(JavaScriptEngine engine, ScriptSource source, Exception e) {
App.getApp().sendBroadcast(new Intent(ACTION_ON_RUN_FINISHED)
.putExtra(EXTRA_EXCEPTION_MESSAGE, e.getMessage()));
e.printStackTrace();
}
};
public static void editFile(Context context, String path) {
editFile(context, null, path);
}
public static void view(Context context, String name, String content) {
context.startActivity(new Intent(context, EditActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.putExtra("readOnly", true)
.putExtra("content", content)
.putExtra("name", name));
}
public static void editFile(Context context, String name, String path) {
context.startActivity(new Intent(context, EditActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
@ -145,7 +109,6 @@ public class EditActivity extends Editor920Activity {
private String mName;
private File mFile;
private View mView;
private DrawerLayout mDrawerLayout;
private EditorDelegate mEditorDelegate;
private SparseArray<ToolbarMenuItem> mMenuMap;
private boolean mReadOnly = false;
@ -175,23 +138,6 @@ public class EditActivity extends Editor920Activity {
registerReceiver(mOnRunFinishedReceiver, new IntentFilter(ACTION_ON_RUN_FINISHED));
}
@Override
protected void onStart() {
super.onStart();
openDrawerIfFirstUse();
}
private void openDrawerIfFirstUse() {
if (Pref.isEditActivityFirstUsing()) {
mDrawerLayout.postDelayed(new Runnable() {
@Override
public void run() {
mDrawerLayout.openDrawer(GravityCompat.END);
}
}, 1000);
}
}
private void handleIntent(Intent intent) {
String path = intent.getStringExtra("path");
mName = intent.getStringExtra("name");
@ -214,25 +160,11 @@ public class EditActivity extends Editor920Activity {
private void setUpUI() {
ThemeColorManager.addActivityStatusBar(this);
mDrawerLayout = (DrawerLayout) mView.findViewById(R.id.drawer_layout);
initSideMenuFragment();
setUpToolbar();
initMenuItem();
ViewBinder.bind(this);
}
private void initSideMenuFragment() {
EditSideMenuFragment.setFragment(EditActivity.this, R.id.fragment_edit_side_menu)
.setOnFunctionClickListener(new FunctionListRecyclerView.OnFunctionClickListener() {
@Override
public void onClick(FunctionListRecyclerView.Function function, int position) {
if (!mReadOnly)
insertText(function.name);
mDrawerLayout.closeDrawer(GravityCompat.END);
}
});
}
private void setUpEditor() {
final EditorView editorView = (EditorView) findViewById(R.id.editor);
mEditorDelegate.setEditorView(editorView);
@ -284,9 +216,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) {
AutoJs.getInstance().getScriptEngineService().execute(new FileScriptSource(mName, mFile), SCRIPT_EXECUTION_LISTENER);
ScriptFileOperation.runOnEditView(new FileScriptSource(mName, mFile));
} else {
AutoJs.getInstance().getScriptEngineService().execute(new StringScriptSource(mName, mEditorDelegate.getText()), SCRIPT_EXECUTION_LISTENER);
ScriptFileOperation.runOnEditView(new StringScriptSource(mName, mEditorDelegate.getText()));
}
}
@ -344,11 +276,19 @@ public class EditActivity extends Editor920Activity {
case R.id.action_beautify:
beautifyCode();
return true;
case R.id.action_open_by_other_apps:
openByOtherApps();
return true;
}
return super.onOptionsItemSelected(item);
}
private void openByOtherApps() {
if (mFile != null)
ScriptFileOperation.openByOtherApps(mFile.getPath());
}
private void beautifyCode() {
final MaterialDialog dialog = MaterialDialogFactory.showProgress(this);
mJsBeautifier.beautify(mEditorDelegate.getText(), new JsBeautifier.Callback() {
@ -365,6 +305,7 @@ public class EditActivity extends Editor920Activity {
@Override
public void onException(Exception e) {
dialog.dismiss();
e.printStackTrace();
}
});

View File

@ -0,0 +1,171 @@
package com.stardust.scriptdroid.ui.edit;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.design.widget.Snackbar;
import android.util.SparseArray;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import com.jecelyin.editor.v2.common.Command;
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.script.StringScriptSource;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.scripts.sample.Sample;
import com.stardust.scriptdroid.ui.BaseActivity;
import com.stardust.scriptdroid.ui.console.ConsoleActivity;
import com.stardust.scriptdroid.ui.edit.editor920.Editor920Activity;
import com.stardust.scriptdroid.ui.edit.editor920.Editor920Utils;
import com.stardust.scriptdroid.ui.help.HelpCatalogueActivity;
import com.stardust.scriptdroid.ui.main.MainActivity;
import com.stardust.scriptdroid.ui.main.operation.ScriptFileOperation;
import com.stardust.theme.ThemeColorManager;
import com.stardust.util.AssetsCache;
import com.stardust.util.SparseArrayEntries;
import com.stardust.view.ViewBinder;
import com.stardust.view.ViewBinding;
import com.stardust.widget.ToolbarMenuItem;
import timber.log.Timber;
import static com.stardust.scriptdroid.ui.main.operation.ScriptFileOperation.ACTION_ON_RUN_FINISHED;
import static com.stardust.scriptdroid.ui.main.operation.ScriptFileOperation.EXTRA_EXCEPTION_MESSAGE;
/**
* Created by Stardust on 2017/4/29.
*/
public class ViewSampleActivity extends Editor920Activity {
public static void view(Context context, Sample sample) {
context.startActivity(new Intent(context, ViewSampleActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.putExtra("sample", sample));
}
private View mView;
private Sample mSample;
private EditorDelegate mEditorDelegate;
private SparseArray<ToolbarMenuItem> mMenuMap;
private BroadcastReceiver mOnRunFinishedReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ACTION_ON_RUN_FINISHED)) {
setMenuStatus(R.id.run, MenuDef.STATUS_NORMAL);
String msg = intent.getStringExtra(EXTRA_EXCEPTION_MESSAGE);
if (msg != null) {
Snackbar.make(mView, getString(R.string.text_error) + ": " + msg, Snackbar.LENGTH_LONG).show();
Timber.e(msg);
}
}
}
};
public void onCreate(Bundle b) {
super.onCreate(b);
setTheme(R.style.EditorTheme);
mView = View.inflate(this, R.layout.activity_view_sample, null);
setContentView(mView);
handleIntent(getIntent());
setUpUI();
setUpEditor();
registerReceiver(mOnRunFinishedReceiver, new IntentFilter(ACTION_ON_RUN_FINISHED));
}
private void handleIntent(Intent intent) {
mSample = (Sample) intent.getSerializableExtra("sample");
String content = AssetsCache.get(this, mSample.path);
mEditorDelegate = new EditorDelegate(0, mSample.name, content);
}
private void setUpUI() {
ThemeColorManager.addActivityStatusBar(this);
setUpToolbar();
initMenuItem();
ViewBinder.bind(this);
}
private void setUpEditor() {
final EditorView editorView = (EditorView) findViewById(R.id.editor);
mEditorDelegate.setEditorView(editorView);
Editor920Utils.setLang(mEditorDelegate, "JavaScript");
editorView.getEditText().setReadOnly(true);
editorView.getEditText().setHorizontallyScrolling(true);
}
private void setUpToolbar() {
BaseActivity.setToolbarAsBack(this, R.id.toolbar, mSample.name);
}
@ViewBinding.Click(R.id.run)
private void run() {
Snackbar.make(mView, R.string.text_start_running, Snackbar.LENGTH_SHORT).show();
setMenuStatus(R.id.run, MenuDef.STATUS_DISABLED);
ScriptFileOperation.runOnEditView(new StringScriptSource(mSample.name, mEditorDelegate.getText()));
}
private void initMenuItem() {
mMenuMap = new SparseArrayEntries<ToolbarMenuItem>()
.entry(R.id.run, (ToolbarMenuItem) findViewById(R.id.run))
.sparseArray();
}
public void setMenuStatus(int menuResId, int status) {
ToolbarMenuItem menuItem = mMenuMap.get(menuResId);
if (menuItem == null)
return;
boolean disabled = status == MenuDef.STATUS_DISABLED;
menuItem.setEnabled(!disabled);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_view_sample, menu);
return true;
}
@Override
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));
return true;
case R.id.action_help:
HelpCatalogueActivity.showMainCatalogue(this);
return true;
case R.id.action_import:
MainActivity.importSample(this, mSample);
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void doCommand(Command command) {
mEditorDelegate.doCommand(command);
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(mOnRunFinishedReceiver);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
try {
super.onRestoreInstanceState(savedInstanceState);
} catch (RuntimeException e) {
// FIXME: 2017/3/20
e.printStackTrace();
}
}
}

View File

@ -9,7 +9,9 @@ import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.Snackbar;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
@ -29,6 +31,7 @@ import com.stardust.scriptdroid.BuildConfig;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.scripts.ScriptFile;
import com.stardust.scriptdroid.scripts.StorageScriptProvider;
import com.stardust.scriptdroid.scripts.sample.Sample;
import com.stardust.scriptdroid.service.AccessibilityWatchDogService;
import com.stardust.scriptdroid.tool.AccessibilityServiceTool;
import com.stardust.scriptdroid.tool.DrawableSaver;
@ -50,6 +53,8 @@ import com.stardust.widget.SlidingUpPanel;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import java.io.IOException;
public class MainActivity extends BaseActivity {
@ -61,6 +66,9 @@ public class MainActivity extends BaseActivity {
private static final String ACTION_IMPORT_SCRIPT = "ACTION_IMPORT_SCRIPT";
private static final String ARGUMENT_SCRIPT = "ARGUMENT_SCRIPT";
private static final String ARGUMENT_PATH = "ARGUMENT_PATH";
private static final String ACTION_IMPORT_SAMPLE = "I cannot find the way back to you...Eating...17.4.29";
private static final String ARGUMENT_SAMPLE = "Take a chance on me...ok...?";
private DrawerLayout mDrawerLayout;
@ViewBinding.Id(R.id.bottom_menu)
@ -70,6 +78,7 @@ public class MainActivity extends BaseActivity {
private OnActivityResultDelegate.Intermediary mActivityResultIntermediary = new OnActivityResultDelegate.Intermediary();
private DrawableSaver mDrawerHeaderBackgroundSaver, mAppbarBackgroundSaver;
private VersionGuard mVersionGuard;
private Intent mIntentToHandle;
@Override
protected void onCreate(Bundle savedInstanceState) {
@ -77,13 +86,12 @@ public class MainActivity extends BaseActivity {
setUpUI();
checkPermissions();
registerBackPressHandlers();
handleIntent(getIntent());
mIntentToHandle = getIntent();
EventBus.getDefault().register(this);
mVersionGuard = new VersionGuard(this);
}
private void registerBackPressHandlers() {
registerBackPressedHandler(new BackPressedHandler() {
@Override
@ -164,6 +172,15 @@ public class MainActivity extends BaseActivity {
viewPager.setAdapter(mPagerAdapter);
viewPager.setOffscreenPageLimit(mPagerAdapter.getCount());
tabLayout.setupWithViewPager(viewPager);
mPagerAdapter.setOnFragmentInstantiateListener(new FragmentPagerAdapterBuilder.OnFragmentInstantiateListener() {
@Override
public void OnInstantiate(Fragment fragment) {
if (fragment instanceof MyScriptListFragment && mIntentToHandle != null) {
handleIntent(mIntentToHandle);
mIntentToHandle = null;
}
}
});
}
@ViewBinding.Click(R.id.add)
@ -183,13 +200,14 @@ public class MainActivity extends BaseActivity {
@ViewBinding.Click(R.id.import_from_file)
private void showFileChooser() {
final StorageScriptProvider provider = StorageScriptProvider.getExternalStorageProvider();
new ScriptFileChooserDialogBuilder(this)
.scriptProvider(StorageScriptProvider.getExternalStorageProvider())
.scriptProvider(provider)
.fileCallback(new ScriptFileChooserDialogBuilder.FileCallback() {
@Override
public void onFileSelection(MaterialDialog dialog, ScriptFile file) {
dialog.dismiss();
StorageScriptProvider.getExternalStorageProvider().clearCacheExceptInitialDirectory();
provider.clearCacheExceptInitialDirectory();
getMyScriptListFragment().importFile(file.getPath());
}
})
@ -203,7 +221,7 @@ public class MainActivity extends BaseActivity {
if (which == DialogAction.POSITIVE) {
dialog.dismiss();
} else {
StorageScriptProvider.getExternalStorageProvider().refreshAll();
provider.refreshAll();
}
}
})
@ -225,6 +243,12 @@ public class MainActivity extends BaseActivity {
mDrawerHeaderBackgroundSaver.select(this, mActivityResultIntermediary);
}
@Override
protected void onResume() {
super.onResume();
mVersionGuard.checkDeprecateAndUpdate();
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
@ -242,9 +266,22 @@ public class MainActivity extends BaseActivity {
case ACTION_IMPORT_SCRIPT:
getMyScriptListFragment().importFile(intent.getStringExtra(ARGUMENT_PATH));
break;
case ACTION_IMPORT_SAMPLE:
importSample((Sample) intent.getSerializableExtra(ARGUMENT_SAMPLE));
break;
}
}
private void importSample(Sample sample) {
try {
getMyScriptListFragment().importFile(sample.name, getAssets().open(sample.path));
} catch (IOException e) {
e.printStackTrace();
Snackbar.make(mDrawerLayout, R.string.text_import_fail, Snackbar.LENGTH_SHORT).show();
}
}
private void handleRecordedScript(final String script) {
new ThemeColorMaterialDialogBuilder(this)
.title(R.string.text_recorded)
@ -280,6 +317,13 @@ public class MainActivity extends BaseActivity {
.putExtra(ARGUMENT_PATH, path));
}
public static void importSample(Context context, Sample sample) {
context.startActivity(new Intent(context, MainActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP)
.putExtra(EXTRA_ACTION, ACTION_IMPORT_SAMPLE)
.putExtra(ARGUMENT_SAMPLE, sample));
}
public MyScriptListFragment getMyScriptListFragment() {
return ((MyScriptListFragment) mPagerAdapter.getStoredFragment(0));
}
@ -308,12 +352,6 @@ public class MainActivity extends BaseActivity {
}
@Override
protected void onResume() {
super.onResume();
mVersionGuard.checkDeprecateAndUpdate();
}
@Override
protected void onDestroy() {
super.onDestroy();

View File

@ -2,23 +2,26 @@ package com.stardust.scriptdroid.ui.main.operation;
import android.content.Intent;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.support.design.widget.Snackbar;
import com.afollestad.materialdialogs.MaterialDialog;
import com.squareup.haha.perflib.Main;
import com.stardust.autojs.ScriptExecutionListener;
import com.stardust.autojs.engine.JavaScriptEngine;
import com.stardust.autojs.script.FileScriptSource;
import com.stardust.autojs.script.ScriptSource;
import com.stardust.autojs.script.StringScriptSource;
import com.stardust.scriptdroid.App;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.autojs.AutoJs;
import com.stardust.scriptdroid.scripts.ScriptFile;
import com.stardust.scriptdroid.scripts.ScriptFileList;
import com.stardust.scriptdroid.external.CommonUtils;
import com.stardust.scriptdroid.external.shortcut.Shortcut;
import com.stardust.scriptdroid.external.shortcut.ShortcutActivity;
import com.stardust.scriptdroid.scripts.ScriptFile;
import com.stardust.scriptdroid.scripts.sample.Sample;
import com.stardust.scriptdroid.ui.edit.EditActivity;
import com.stardust.theme.dialog.ThemeColorMaterialDialogBuilder;
import com.stardust.scriptdroid.App;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.ui.main.MainActivity;
import org.greenrobot.eventbus.EventBus;
import java.io.IOException;
/**
* Created by Stardust on 2017/1/23.
@ -26,17 +29,34 @@ import org.greenrobot.eventbus.EventBus;
public abstract class ScriptFileOperation {
public static final String ACTION_ON_RUN_FINISHED = "ACTION_ON_RUN_FINISHED";
public static final String EXTRA_EXCEPTION_MESSAGE = "EXTRA_EXCEPTION_MESSAGE";
public static class ShowMessageEvent {
public int messageResId;
public ShowMessageEvent(int message) {
this.messageResId = message;
private static final ScriptExecutionListener SCRIPT_EXECUTION_LISTENER = new ScriptExecutionListener() {
@Override
public void onStart(JavaScriptEngine engine, ScriptSource source) {
AutoJs.getInstance().getScriptEngineService().getDefaultListener().onStart(engine, source);
}
}
public static void openByOtherApps(ScriptFile scriptFile) {
Uri uri = Uri.parse("file://" + scriptFile.getPath());
@Override
public void onSuccess(JavaScriptEngine engine, ScriptSource source, Object result) {
App.getApp().sendBroadcast(new Intent(ACTION_ON_RUN_FINISHED));
}
@Override
public void onException(JavaScriptEngine engine, ScriptSource source, Exception e) {
App.getApp().sendBroadcast(new Intent(ACTION_ON_RUN_FINISHED)
.putExtra(EXTRA_EXCEPTION_MESSAGE, e.getMessage()));
e.printStackTrace();
}
};
public static void openByOtherApps(String path) {
Uri uri = Uri.parse("file://" + path);
App.getApp().startActivity(new Intent(Intent.ACTION_VIEW).setDataAndType(uri, "text/plain").addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}
@ -53,149 +73,12 @@ public abstract class ScriptFileOperation {
EditActivity.editFile(App.getApp(), file.getSimplifiedName(), file.getPath());
}
public abstract void operate(RecyclerView recyclerView, ScriptFileList scriptFileList, int position);
private String mName;
public ScriptFileOperation(String name, int iconResId) {
mName = name;
mIconResId = iconResId;
public static void run(ScriptFile file) {
AutoJs.getInstance().getScriptEngineService().execute(new FileScriptSource(file));
}
private int mIconResId;
public String getName() {
return mName;
public static void runOnEditView(ScriptSource scriptSource) {
AutoJs.getInstance().getScriptEngineService().execute(scriptSource, SCRIPT_EXECUTION_LISTENER);
}
public int getIconResId() {
return mIconResId;
}
public static class Run extends ScriptFileOperation {
public Run() {
super(App.getApp().getString(R.string.text_run), R.drawable.ic_play_green);
}
@Override
public void operate(RecyclerView recyclerView, ScriptFileList scriptFileList, int position) {
EventBus.getDefault().post(new ShowMessageEvent(R.string.text_start_running));
ScriptFile scriptFile = scriptFileList.get(position);
AutoJs.getInstance().getScriptEngineService().execute(new FileScriptSource(scriptFile));
}
}
public static class Edit extends ScriptFileOperation {
private static Edit instance = new Edit();
public Edit() {
super(App.getApp().getString(R.string.text_edit), R.drawable.ic_edit_green_48dp);
}
public static Edit getInstance() {
return instance;
}
public static void setInstance(Edit instance) {
Edit.instance = instance;
}
@Override
public void operate(RecyclerView recyclerView, ScriptFileList scriptFileList, int position) {
ScriptFile scriptFile = scriptFileList.get(position);
EditActivity.editFile(App.getApp(), scriptFile.getSimplifiedName(), scriptFile.getPath());
//脚本
//任务&控制台
//教程
//
}
}
public static class OpenByOtherApp extends ScriptFileOperation {
public OpenByOtherApp() {
super(App.getApp().getString(R.string.text_open_by_other_apps), R.drawable.ic_open_in_new_green_48dp);
}
@Override
public void operate(RecyclerView recyclerView, ScriptFileList scriptFileList, int position) {
ScriptFile scriptFile = scriptFileList.get(position);
Uri uri = Uri.parse("file://" + scriptFile.getPath());
App.getApp().startActivity(new Intent(Intent.ACTION_VIEW).setDataAndType(uri, "text/plain").addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}
}
public static class Rename extends ScriptFileOperation {
public Rename() {
super(App.getApp().getString(R.string.text_rename), R.drawable.ic_rename_green);
}
@Override
public void operate(final RecyclerView recyclerView, final ScriptFileList scriptFileList, final int position) {
String oldName = scriptFileList.get(position).getSimplifiedName();
new ThemeColorMaterialDialogBuilder(recyclerView.getContext())
.title(R.string.text_rename)
.checkBoxPrompt(App.getApp().getString(R.string.text_rename_file_meanwhile), false, null)
.input(App.getApp().getString(R.string.text_please_input_new_name), oldName, new MaterialDialog.InputCallback() {
@Override
public void onInput(@NonNull MaterialDialog dialog, CharSequence input) {
scriptFileList.rename(position, input.toString(), dialog.isPromptCheckBoxChecked());
recyclerView.getAdapter().notifyItemChanged(position);
}
})
.show();
}
}
public static class CreateShortcut extends ScriptFileOperation {
public CreateShortcut() {
super(App.getApp().getString(R.string.text_send_shortcut), R.drawable.ic_shortcut_green);
}
@Override
public void operate(RecyclerView recyclerView, ScriptFileList scriptFileList, int position) {
ScriptFile scriptFile = scriptFileList.get(position);
new Shortcut(App.getApp()).name(scriptFile.getSimplifiedName())
.targetClass(ShortcutActivity.class)
.icon(R.drawable.ic_robot_green)
.extras(new Intent().putExtra("path", scriptFile.getPath()))
.send();
EventBus.getDefault().post(R.string.text_already_create);
}
}
public static class Remove extends ScriptFileOperation {
public Remove() {
super(App.getApp().getString(R.string.text_delete), R.drawable.ic_delete_green_48dp);
}
@Override
public void operate(RecyclerView recyclerView, ScriptFileList scriptFileList, int position) {
scriptFileList.remove(position);
recyclerView.getAdapter().notifyItemRemoved(position);
}
}
public static class Delete extends ScriptFileOperation {
public Delete() {
super(App.getApp().getString(R.string.text_delete_absolutly), R.drawable.ic_delete_forever_green_48dp);
}
@Override
public void operate(RecyclerView recyclerView, ScriptFileList scriptFileList, int position) {
boolean succeed = scriptFileList.deleteFromFileSystem(position);
EventBus.getDefault().post(new ShowMessageEvent(succeed ? R.string.text_already_delete : R.string.text_delete_failed));
if (succeed)
recyclerView.getAdapter().notifyItemRemoved(position);
}
}
}
}

View File

@ -1,174 +0,0 @@
package com.stardust.scriptdroid.ui.main.operation;
import android.content.Context;
import android.graphics.drawable.ColorDrawable;
import android.support.annotation.Nullable;
import android.support.v4.widget.PopupWindowCompat;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.PopupWindow;
import android.widget.TextView;
import android.workground.WrapContentLinearLayoutManager;
import com.stardust.util.ViewUtil;
import com.stardust.scriptdroid.R;
import java.util.List;
/**
* Created by Stardust on 2017/1/24.
*/
public class ScriptFileOperationPopupMenu extends PopupWindow {
public interface OnItemClickListener {
void onClick(View view, int position, ScriptFileOperation operation);
}
private Context mContext;
private ScriptFileOperationListRecyclerView mOperationListRecyclerView;
private OnItemClickListener mOnItemClickListener;
private List<ScriptFileOperation> mScriptFileOperationList;
private final View.OnClickListener mOnItemClickRealListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mOnItemClickListener != null) {
int position = mOperationListRecyclerView.getChildViewHolder(v).getAdapterPosition();
mOnItemClickListener.onClick(v, position, mScriptFileOperationList.get(position));
}
}
};
public ScriptFileOperationPopupMenu(Context context, List<ScriptFileOperation> scriptFileOperationList) {
super(context);
mContext = context;
mScriptFileOperationList = scriptFileOperationList;
init();
}
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
mOnItemClickListener = onItemClickListener;
}
public void show(View anchor) {
int y = (int) (getScreenHeight() - anchor.getHeight() - getYInScreen(anchor) - getContentHeight());
y = Math.min(y, -anchor.getHeight());
PopupWindowCompat.showAsDropDown(this, anchor, 0, y, Gravity.LEFT | Gravity.BOTTOM);
}
private int getContentHeight() {
getContentView().measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
return getContentView().getMeasuredHeight();
}
private int getYInScreen(View anchor) {
int[] location = new int[2];
anchor.getLocationInWindow(location);
return location[1];
}
private float getScreenHeight() {
DisplayMetrics displaymetrics = new DisplayMetrics();
((WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getMetrics(displaymetrics);
return displaymetrics.heightPixels;
}
private void init() {
setWidth(WindowManager.LayoutParams.WRAP_CONTENT);
setHeight(WindowManager.LayoutParams.WRAP_CONTENT);
setBackgroundDrawable(new ColorDrawable());
setOutsideTouchable(true);
setAnimationStyle(-1);
initContentView();
}
private void initContentView() {
View contentView = View.inflate(mContext, R.layout.script_file_operation_popup_menu_content, null);
setContentView(contentView);
mOperationListRecyclerView = ViewUtil.$(contentView, R.id.operation_list);
mOperationListRecyclerView.setOnItemClickListener(mOnItemClickRealListener);
mOperationListRecyclerView.setScriptFileOperationList(mScriptFileOperationList);
}
public static class ScriptFileOperationListRecyclerView extends RecyclerView {
private OnClickListener mOnItemClickListener;
private List<ScriptFileOperation> mScriptFileOperationList;
public ScriptFileOperationListRecyclerView(Context context) {
super(context);
init();
}
public ScriptFileOperationListRecyclerView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public ScriptFileOperationListRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public void setScriptFileOperationList(List<ScriptFileOperation> scriptFileOperationList) {
mScriptFileOperationList = scriptFileOperationList;
}
private void init() {
setLayoutManager(new WrapContentLinearLayoutManager(getContext()));
setAdapter(new Adapter<ViewHolder>() {
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(getContext()).inflate(R.layout.script_file_operation_popup_menu_item, parent, false);
return new ViewHolder(itemView);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
ScriptFileOperation operation = mScriptFileOperationList.get(position);
holder.operationName.setText(operation.getName());
holder.icon.setImageResource(operation.getIconResId());
}
@Override
public int getItemCount() {
return mScriptFileOperationList.size();
}
});
}
public void setOnItemClickListener(OnClickListener onItemClickListener) {
mOnItemClickListener = onItemClickListener;
}
private class ViewHolder extends RecyclerView.ViewHolder {
TextView operationName;
ImageView icon;
ViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(mOnItemClickListener);
operationName = ViewUtil.$(itemView, R.id.name);
icon = ViewUtil.$(itemView, R.id.icon);
}
}
}
}

View File

@ -9,13 +9,11 @@ import android.view.ViewGroup;
import com.afollestad.materialdialogs.MaterialDialog;
import com.stardust.app.Fragment;
import com.stardust.pio.PFile;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.scripts.sample.Sample;
import com.stardust.scriptdroid.scripts.sample.SampleFileManager;
import com.stardust.scriptdroid.ui.edit.EditActivity;
import com.stardust.scriptdroid.ui.edit.ViewSampleActivity;
import com.stardust.scriptdroid.ui.main.MainActivity;
import com.stardust.util.AssetsCache;
import java.io.IOException;
@ -67,6 +65,7 @@ public class SampleScriptListFragment extends Fragment {
}
private void copySampleToMyScripts(Sample sample) {
MainActivity.importSample(getActivity(), sample);
try {
((MainActivity) getActivity()).getMyScriptListFragment().
importFile(sample.name, getActivity().getAssets().open(sample.path));
@ -77,7 +76,7 @@ public class SampleScriptListFragment extends Fragment {
}
private void viewSample(Sample sample) {
EditActivity.view(getContext(), sample.name, AssetsCache.get(getActivity(), sample.path));
ViewSampleActivity.view(getContext(), sample);
}
}

View File

@ -5,6 +5,7 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.text.InputType;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -37,6 +38,8 @@ public class MyScriptListFragment extends Fragment {
public static final String MESSAGE_SCRIPT_FILE_ADDED = "MESSAGE_SCRIPT_FILE_ADDED";
private static final String TAG = "MyScriptListFragment";
private ScriptAndFolderListRecyclerView mScriptListRecyclerView;
private ScriptListWithProgressBarView mScriptListWithProgressBarView;
private View mNoScriptHint;
@ -45,7 +48,7 @@ public class MyScriptListFragment extends Fragment {
private ScriptFile mSelectedScriptFile;
private MaterialDialog.InputCallback mFileNameInputCallback = new InputCallback(false);
private MaterialDialog.InputCallback mDirectoryNameInputCallback = new InputCallback(true);
private int mSelectedPosition;
private String mFilePathToImport;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
@ -67,6 +70,10 @@ public class MyScriptListFragment extends Fragment {
mNoScriptHint = $(R.id.hint_no_script);
initScriptListRecyclerView();
initDialogs();
if (mFilePathToImport != null) {
importFile(mFilePathToImport);
mFilePathToImport = null;
}
}
private void initScriptListRecyclerView() {
@ -91,7 +98,6 @@ public class MyScriptListFragment extends Fragment {
@Override
public void onLongClick(ScriptFile file, int position) {
mSelectedScriptFile = file;
mSelectedPosition = position;
if (file.isDirectory()) {
mDirectoryOperationDialog.show();
} else {
@ -147,6 +153,10 @@ public class MyScriptListFragment extends Fragment {
}
public void importFile(final String pathFrom) {
if (getActivity() == null) {
mFilePathToImport = pathFrom;
return;
}
try {
importFile(PFile.getNameWithoutExtension(pathFrom), new FileInputStream(pathFrom));
} catch (FileNotFoundException e) {
@ -245,7 +255,7 @@ public class MyScriptListFragment extends Fragment {
@ViewBinding.Click(R.id.open_by_other_apps)
private void openByOtherApps() {
dismissDialogs();
ScriptFileOperation.openByOtherApps(mSelectedScriptFile);
ScriptFileOperation.openByOtherApps(mSelectedScriptFile.getPath());
onScriptFileOperated();
}

View File

@ -20,6 +20,7 @@ import com.stardust.scriptdroid.autojs.AutoJs;
import com.stardust.scriptdroid.scripts.ScriptFile;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.scripts.StorageScriptProvider;
import com.stardust.scriptdroid.ui.main.operation.ScriptFileOperation;
import com.stardust.widget.ViewHolderMutableAdapter;
import com.stardust.widget.ViewHolderSupplier;
import com.yqritc.recyclerviewflexibledivider.HorizontalDividerItemDecoration;
@ -107,7 +108,7 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView {
public void onClick(View v) {
int position = getChildViewHolder((View) v.getParent()).getAdapterPosition();
ScriptFile file = mAdapter.getScriptFileAt(position);
AutoJs.getInstance().getScriptEngineService().execute(new FileScriptSource(file));
ScriptFileOperation.run(file);
}
};
private final ViewHolderSupplier<ViewHolder> mDefaultViewHolderSupplier = new ViewHolderSupplier<ViewHolder>() {
@ -188,6 +189,10 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView {
setRootDirectory(mStorageScriptProvider.getInitialDirectory());
}
public StorageScriptProvider getStorageScriptProvider() {
return mStorageScriptProvider;
}
public void setOnItemClickListener(OnScriptFileClickListener onItemClickListener) {
mOnItemClickListener = onItemClickListener;
}

View File

@ -1,151 +0,0 @@
package com.stardust.scriptdroid.ui.main.script_list;
import android.content.Context;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.ThemeColorRecyclerView;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.workground.WrapContentLinearLayoutManager;
import com.stardust.scriptdroid.scripts.ScriptFile;
import com.stardust.scriptdroid.scripts.ScriptFileList;
import com.stardust.util.ViewUtil;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.ui.main.operation.ScriptFileOperation;
import org.greenrobot.eventbus.Subscribe;
/**
* Created by Stardust on 2017/1/23.
*/
public class ScriptListRecyclerView extends ThemeColorRecyclerView {
public interface OnItemClickListener {
void OnItemClick(View v, int position);
}
private ScriptFileList mScriptFileList;
private OnItemClickListener mOnItemClickListener;
private final OnClickListener mOnItemClickListenerProxy = new OnClickListener() {
@Override
public void onClick(View v) {
int position = getChildViewHolder(v).getAdapterPosition();
if (mOnItemClickListener != null) {
mOnItemClickListener.OnItemClick(v, position);
}
}
};
private final OnClickListener mOnEditIconClickListener = new OnClickListener() {
@Override
public void onClick(View v) {
int position = getChildViewHolder((View) v.getParent()).getAdapterPosition();
onEditIconClick(v, position);
}
};
private final OnClickListener mOnRunIconClickListener = new OnClickListener() {
@Override
public void onClick(View v) {
int position = getChildViewHolder((View) v.getParent()).getAdapterPosition();
//onRunIconClick(v, position);
}
};
public ScriptListRecyclerView(Context context) {
super(context);
init();
}
public ScriptListRecyclerView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public ScriptListRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
mOnItemClickListener = onItemClickListener;
}
private void init() {
setAdapter(new Adapter());
setLayoutManager(new WrapContentLinearLayoutManager(getContext()));
addItemDecoration(new DividerItemDecoration(getContext(), DividerItemDecoration.VERTICAL));
}
protected void onEditIconClick(View v, int position) {
ScriptFileOperation.Edit.getInstance().operate(ScriptListRecyclerView.this, mScriptFileList, position);
}
public void setScriptFileList(ScriptFileList scriptFileList) {
mScriptFileList = scriptFileList;
getAdapter().notifyDataSetChanged();
}
@Subscribe
public void showMessage(ScriptFileOperation.ShowMessageEvent event) {
Snackbar.make(this, event.messageResId, Snackbar.LENGTH_SHORT).show();
}
private class Adapter extends RecyclerView.Adapter<ViewHolder> {
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(getContext()).inflate(R.layout.script_list_recycler_view_item, parent, false);
return new ViewHolder(itemView);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
ScriptFile scriptFile = mScriptFileList.get(position);
holder.name.setText(scriptFile.getSimplifiedName());
holder.path.setText(scriptFile.getSimplifiedPath());
}
@Override
public int getItemCount() {
return mScriptFileList.size();
}
@Override
public void registerAdapterDataObserver(AdapterDataObserver observer) {
super.registerAdapterDataObserver(observer);
}
}
private class ViewHolder extends RecyclerView.ViewHolder {
TextView name, path;
ViewHolder(View itemView) {
super(itemView);
name = (TextView) itemView.findViewById(R.id.name);
path = (TextView) itemView.findViewById(R.id.path);
ViewUtil.$(itemView, R.id.edit).setOnClickListener(mOnEditIconClickListener);
ViewUtil.$(itemView, R.id.run).setOnClickListener(mOnRunIconClickListener);
itemView.setOnClickListener(mOnItemClickListenerProxy);
}
}
}

View File

@ -7,6 +7,7 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.support.annotation.StyleRes;
import android.support.v4.widget.SwipeRefreshLayout;
import android.util.AttributeSet;
import android.view.View;
import android.widget.FrameLayout;
@ -23,6 +24,7 @@ public class ScriptListWithProgressBarView extends FrameLayout {
private View mProgressBar;
private ScriptAndFolderListRecyclerView mScriptAndFolderListRecyclerView;
private SwipeRefreshLayout mSwipeRefreshLayout;
public ScriptListWithProgressBarView(@NonNull Context context) {
super(context);
@ -47,6 +49,7 @@ public class ScriptListWithProgressBarView extends FrameLayout {
private void init() {
inflate(getContext(), R.layout.script_and_folder_list_view, this);
mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh_layout);
mProgressBar = findViewById(R.id.progressBar);
mScriptAndFolderListRecyclerView = (ScriptAndFolderListRecyclerView) findViewById(R.id.script_list_recycler_view);
mScriptAndFolderListRecyclerView.setFileProcessListener(new ScriptAndFolderListRecyclerView.FileProcessListener() {
@ -60,6 +63,12 @@ public class ScriptListWithProgressBarView extends FrameLayout {
hideProgressBar();
}
});
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
mScriptAndFolderListRecyclerView.getStorageScriptProvider().refreshAll();
}
});
}
@ -82,11 +91,13 @@ public class ScriptListWithProgressBarView extends FrameLayout {
public void showProgressBar() {
mProgressBar.setVisibility(VISIBLE);
mSwipeRefreshLayout.setRefreshing(true);
mScriptAndFolderListRecyclerView.setEnabled(false);
}
public void hideProgressBar() {
mProgressBar.setVisibility(GONE);
mSwipeRefreshLayout.setRefreshing(false);
mScriptAndFolderListRecyclerView.setEnabled(true);
}

View File

@ -115,6 +115,7 @@ public class SettingsActivity extends BaseActivity {
@Override
public void run() {
EventBus.getDefault().post(new MessageEvent(MainActivity.MESSAGE_CLEAR_BACKGROUND_SETTINGS));
Toast.makeText(getActivity(), R.string.text_already_reset, Toast.LENGTH_SHORT).show();
}
})
.entry(getString(R.string.text_check_update), new Runnable() {

View File

@ -6,6 +6,7 @@ import android.support.annotation.NonNull;
import com.afollestad.materialdialogs.DialogAction;
import com.afollestad.materialdialogs.MaterialDialog;
import com.stardust.scriptdroid.BuildConfig;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.tool.UpdateChecker;
import com.stardust.scriptdroid.tool.VersionInfo;
@ -43,7 +44,7 @@ public class VersionGuard {
if (isCurrentVersionDeprecated) {
showDeprecatedDialogIfNeeded();
} else {
showUpdateInfo(info);
showUpdateInfoIfNeeded(info);
}
}
});
@ -51,10 +52,12 @@ public class VersionGuard {
}
}
private void showUpdateInfo(UpdateChecker.UpdateInfo info) {
new UpdateInfoDialogBuilder(mActivity, info)
.showDoNotAskAgain()
.show();
private void showUpdateInfoIfNeeded(UpdateChecker.UpdateInfo info) {
if (BuildConfig.VERSION_CODE < info.versionCode) {
new UpdateInfoDialogBuilder(mActivity, info)
.showDoNotAskAgain()
.show();
}
}
private void showDeprecatedDialogIfNeeded() {

View File

@ -50,6 +50,7 @@ public class SlidingUpPanel extends FrameLayout {
public void show() {
setVisibility(VISIBLE);
setClickable(true);
mContentContainer.startAnimation(mSlideUpAnimation);
mShowing = true;
}

View File

@ -63,20 +63,6 @@
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.DrawerLayout
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@layout/content_edit"/>
<FrameLayout
android:id="@+id/fragment_edit_side_menu"
android:layout_width="280dp"
android:layout_height="match_parent"
android:layout_gravity="end"
android:background="@android:color/white"
android:clickable="true"/>
</android.support.v4.widget.DrawerLayout>
<include layout="@layout/content_edit"/>
</LinearLayout>

View File

@ -0,0 +1,86 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.stardust.scriptdroid.ui.edit.EditActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<com.stardust.theme.widget.ThemeColorToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:title="@string/_app_name"
app:popupTheme="@style/AppTheme.PopupOverlay">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="right"
android:orientation="horizontal">
<com.stardust.widget.ToolbarMenuItem
android:id="@+id/run"
android:layout_width="40dp"
android:layout_height="match_parent"
app:icon="@drawable/ic_play_arrow_white_48dp"
app:icon_color="@android:color/white"
app:text="@string/text_run"/>
</LinearLayout>
</com.stardust.theme.widget.ThemeColorToolbar>
</android.support.design.widget.AppBarLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffffff"
android:orientation="vertical"
tools:showIn="@layout/activity_edit">
<com.jecelyin.editor.v2.view.EditorView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/editor"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<com.jecelyin.editor.v2.core.widget.JecEditText
android:id="@+id/edit_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffffff"
android:enabled="true"
android:gravity="start|top"
android:inputType="textMultiLine"
android:padding="5dp"
android:scrollbarThumbVertical="@android:color/transparent"
android:scrollbarTrackVertical="@null"
android:scrollbars="vertical"/>
<me.zhanghai.android.materialprogressbar.MaterialProgressBar
android:id="@+id/progress_view"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_centerHorizontal="true"
android:layout_marginTop="90dp"
android:indeterminate="true"
android:visibility="gone"/>
</com.jecelyin.editor.v2.view.EditorView>
</LinearLayout>
</LinearLayout>

View File

@ -36,7 +36,7 @@
<android.support.v7.widget.Toolbar
android:id="@+id/air_toolbar"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"/>
android:layout_height="wrap_content"/>
</android.support.design.widget.AppBarLayout>
@ -52,12 +52,12 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:orientation="vertical"
android:padding="@dimen/air_baseline_card"
android:clipToPadding="false">
android:padding="@dimen/air_baseline_card">
<include
layout="@layout/air_card_report"
layout="@layout/air_card_report_compat"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
@ -82,8 +82,7 @@
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/air_baseline"
app:srcCompat="@drawable/air_ic_send_light"
app:backgroundTint="?colorAccent"/>
app:srcCompat="@drawable/air_ic_send_light"/>
</FrameLayout>

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ MIT License
~
~ Copyright (c) 2017 Jan Heinrich Reimer
~
~ Permission is hereby granted, free of charge, to any person obtaining a copy
~ of this software and associated documentation files (the "Software"), to deal
~ in the Software without restriction, including without limitation the rights
~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
~ copies of the Software, and to permit persons to whom the Software is
~ furnished to do so, subject to the following conditions:
~
~ The above copyright notice and this permission notice shall be included in all
~ copies or substantial portions of the Software.
~
~ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
~ SOFTWARE.
-->
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:cardBackgroundColor="?cardBackgroundColor">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="@dimen/air_baseline">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/air_title_issue"
android:textAppearance="@style/TextAppearance.AppCompat.Body2"
android:textColor="?android:textColorSecondary"/>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/air_baseline">
<android.support.design.widget.TextInputEditText
android:id="@+id/air_inputTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/air_label_issue_title"
android:inputType="textCapSentences"
android:maxLines="1"/>
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/air_baseline_half">
<android.support.design.widget.TextInputEditText
android:id="@+id/air_inputDescription"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/air_label_issue_description"
android:inputType="textMultiLine|textCapSentences"
android:lines="2"
android:scrollbars="vertical"/>
</android.support.design.widget.TextInputLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/air_baseline"
android:gravity="center_vertical">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/air_label_device_info"
android:textAppearance="@style/TextAppearance.AppCompat.Subhead"/>
<android.support.v7.widget.AppCompatImageButton
android:id="@+id/air_buttonDeviceInfo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?selectableItemBackgroundBorderless"
android:contentDescription="@string/air_label_device_info"
android:padding="@dimen/air_icon_padding"
android:tint="#ee000000"
app:srcCompat="@drawable/air_ic_expand_more"/>
</LinearLayout>
<com.github.aakira.expandablelayout.ExpandableRelativeLayout
android:id="@+id/air_layoutDeviceInfo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:ael_expanded="false"
app:ael_interpolator="fastOutSlowIn"
app:ael_orientation="vertical">
<android.support.v7.widget.AppCompatTextView
android:id="@+id/air_textDeviceInfo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/air_baseline_half"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
android:textColor="?android:textColorSecondary"/>
</com.github.aakira.expandablelayout.ExpandableRelativeLayout>
</LinearLayout>
</android.support.v7.widget.CardView>

View File

@ -4,10 +4,17 @@
android:layout_height="match_parent"
android:background="#fefefe">
<com.stardust.scriptdroid.ui.main.script_list.ScriptAndFolderListRecyclerView
android:id="@+id/script_list_recycler_view"
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swipe_refresh_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
android:layout_height="match_parent">
<com.stardust.scriptdroid.ui.main.script_list.ScriptAndFolderListRecyclerView
android:id="@+id/script_list_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</android.support.v4.widget.SwipeRefreshLayout>
<FrameLayout
android:id="@+id/progressBar"

View File

@ -1,14 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:drawable/dialog_holo_light_frame"
android:orientation="vertical">
<view
android:id="@+id/operation_list"
class="com.stardust.scriptdroid.ui.main.operation.ScriptFileOperationPopupMenu$ScriptFileOperationListRecyclerView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>

View File

@ -1,27 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="52dp"
android:background="?android:selectableItemBackground"
android:orientation="horizontal"
android:padding="16dp">
<com.stardust.theme.widget.ThemeColorImageView
android:id="@+id/icon"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:contentDescription="@string/_app_name"/>
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="16dp"
android:layout_toRightOf="@id/icon"
android:textColor="@android:color/secondary_text_light"
android:textSize="16sp"/>
</RelativeLayout>

View File

@ -9,15 +9,21 @@
app:showAsAction="never"/>
<item
android:id="@+id/action_help"
android:id="@+id/action_console"
android:orderInCategory="200"
android:title="@string/text_console"
app:showAsAction="never"/>
<item
android:id="@+id/action_help"
android:orderInCategory="300"
android:title="@string/text_help"
app:showAsAction="never"/>
<item
android:id="@+id/action_console"
android:orderInCategory="300"
android:title="@string/text_console"
android:id="@+id/action_open_by_other_apps"
android:orderInCategory="400"
android:title="@string/text_open_by_other_apps"
app:showAsAction="never"/>
</menu>

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_console"
android:orderInCategory="200"
android:title="@string/text_console"
app:showAsAction="never"/>
<item
android:id="@+id/action_help"
android:orderInCategory="300"
android:title="@string/text_help"
app:showAsAction="never"/>
<item
android:id="@+id/action_import"
android:orderInCategory="400"
android:title="@string/text_copy_to_my_scripts"
app:showAsAction="never"/>
</menu>

View File

@ -1,5 +1,5 @@
<resources>
<string name="_app_name">UiAutomator</string>
<string name="_app_name">AutoJs</string>
<string name="action_settings">Settings</string>
<string name="action_disable_service">Disable Service</string>
<string name="text_accessibility_service_description">Required by the script automatic operation (click, long press, slide, etc.).</string>
@ -38,8 +38,6 @@
<string name="text_do_not_remind_again">Don\'t show again</string>
<string name="copyright">Copyright©2016 All right reserves.</string>
<string name="developer">Stardust</string>
<string name="qq">946994919</string>
<string name="email">hybbbb1996@gmail.com</string>
<string name="github">Source Code</string>
<string name="text_already_copy_to_clip">Copied</string>
<string name="donate_developer">Donate</string>
@ -122,7 +120,7 @@
<string name="text_layout_hierarchy">View layout hierarchy</string>
<string name="text_layout_bounds">View layout bounds</string>
<string name="text_no_accessibility_permission_to_capture">Accessibility service is not activated</string>
<string name="text_sample_script">Sample Scripts</string>
<string name="text_sample_script">Samples</string>
<string name="text_my_script">My Scripts</string>
<string name="hint_no_script">Click ADD to create your first script~(。・・)</string>
<string name="text_reset_background">Reset background settings</string>
@ -155,15 +153,15 @@
<string name="summary_command_run_mode">If the app responses slowly when running script, choose Thread Pool or Create Thread. But it may causes rebooting of the device</string>
<string name="text_on">ON</string>
<string name="text_off">OFF</string>
<string name="text_please_choose_file_to_import">请选择要导入的脚本</string>
<string name="text_refresh">刷新</string>
<string name="notice_no_running_script"><![CDATA[没有正在运行的脚本 φ(>ω<*)]]></string>
<string name="text_checking_update">正在检查更新</string>
<string name="text_new_version">新版本</string>
<string name="text_is_latest_version">已经是最新版本</string>
<string name="text_version_too_old">版本过低</string>
<string name="warning_version_too_old">这个版本已经不能再使用了哦</string>
<string name="text_release_notes">更新日志</string>
<string name="text_please_choose_file_to_import">Select script file to import</string>
<string name="text_refresh">Refresh</string>
<string name="notice_no_running_script"><![CDATA[No running script φ(>ω<*)]]></string>
<string name="text_checking_update">Checking for updates</string>
<string name="text_new_version">New Version</string>
<string name="text_is_latest_version">No newer version found</string>
<string name="text_version_too_old">Version too old</string>
<string name="warning_version_too_old">This version is deprecated</string>
<string name="text_release_notes">Release Notes</string>
<string-array name="record_control_keys">
<item>None</item>
<item>Volume Up</item>
@ -176,5 +174,15 @@
<item>Create New Thread Every Time</item>
<item>Thread Pool</item>
</string-array>
<string name="text_update">Update</string>
<string name="text_task_manage">Tasks</string>
<string name="text_script">Script</string>
<string name="text_root_script_record"></string>
<string name="text_processing">Processing</string>
<string name="text_re_import_succeed"></string>
<string name="text_pre_execute_script">Pre-execute script</string>
<string name="text_check_update">Check for updates</string>
<string name="text_new_directory">New Directory</string>
<string name="text_already_reset">已重置</string>
</resources>

View File

@ -1,5 +1,5 @@
<resources>
<string name="_app_name">免Root脚本精灵</string>
<string name="_app_name">AutoJs</string>
<string name="action_settings">设置</string>
<string name="action_disable_service">关闭服务</string>
<string name="text_accessibility_service_description">使脚本自动操作(点击、长按、滑动等)所需,若关闭则只能执行不涉及自动操作的脚本。</string>
@ -12,7 +12,7 @@
<string name="text_please_input_name">请输入名称</string>
<string name="text_name">名称</string>
<string name="text_go_to_setting">去设置</string>
<string name="explain_accessibility_permission">软件需要打开\"自动操作服务\"才能运行,请在随后的设置中选择\"免Root脚本精灵\"并开启服务。\n您也可以稍后在侧拉菜单中设置。</string>
<string name="explain_accessibility_permission">软件需要打开\"自动操作服务\"才能运行,请在随后的设置中选择\"AutoJs\"并开启服务。\n您也可以稍后在侧拉菜单中设置。</string>
<string name="text_cancel">取消</string>
<string name="text_path_is_empty">路径为空</string>
<string name="text_file_not_exists">文件不存在</string>
@ -42,14 +42,14 @@
<string name="text_sample_simple_calculator">示例:简单计算器</string>
<string name="copyright">Copyright©2016 All right reserves.</string>
<string name="developer">星尘幻影</string>
<string name="qq">946994919</string>
<string name="qq">2732014414</string>
<string name="email">hybbbb1996@gmail.com</string>
<string name="github">软件源代码</string>
<string name="text_already_copy_to_clip">已复制到剪贴板</string>
<string name="donate_developer">打赏作者</string>
<string name="text_email">邮箱</string>
<string name="my_github">https://github.com/hyb1996/NoRootScriptDroid</string>
<string name="share_app">[免Root脚本精灵]下载地址http://www.coolapk.com/apk/com.stardust.scriptdroid </string>
<string name="share_app">[AutoJs]下载地址http://www.coolapk.com/apk/com.stardust.scriptdroid </string>
<string name="text_floating_window">悬浮窗</string>
<string name="text_assist_service_notification">通知栏点击区域辅助开关</string>
<string name="text_others">其他</string>
@ -165,7 +165,7 @@
<string name="key_stop_record_trigger">key_stop_record_trigger</string>
<string name="text_current_activity">当前活动:</string>
<string name="text_current_package">当前应用包名:</string>
<string name="go_to_accessibility_settings"><![CDATA[请打开设置->无障碍服务->免Root脚本精灵并开启]]></string>
<string name="go_to_accessibility_settings"><![CDATA[请打开设置->无障碍服务->AutoJs并开启]]></string>
<string name="text_script_running">脚本运行</string>
<string name="key_use_volume_control_running">key_use_volume_control_running</string>
<string name="text_use_volume_to_stop_running">每次音量键变化停止所有脚本</string>
@ -210,6 +210,10 @@
<string name="text_do_not_ask_again_for_this_version">此版本不再提示</string>
<string name="text_code_beautify">格式化代码</string>
<string name="text_processing">处理中</string>
<string name="text_already_reset">已重置</string>
<string name="text_guard_mode">保护模式</string>
<string name="summary_guard_mode">在本软件界面无法运行自动操作命令以免误触</string>
<string name="key_guard_mode">key_guard_mode</string>
<string-array name="record_control_keys">
<item></item>

View File

@ -35,6 +35,12 @@
android:defaultValue="false"
android:key="@string/key_use_volume_control_running"
android:title="@string/text_use_volume_to_stop_running"/>
<com.stardust.theme.preference.ThemeColorSwitchPreference
android:defaultValue="false"
android:key="@string/key_guard_mode"
android:summary="@string/summary_guard_mode"
android:title="@string/text_guard_mode"/>
</com.stardust.theme.preference.ThemeColorPreferenceCategory>
<com.stardust.theme.preference.ThemeColorPreferenceCategory android:title="@string/text_edit">
@ -60,26 +66,12 @@
<Preference android:title="@string/text_reset_background"/>
</com.stardust.theme.preference.ThemeColorPreferenceCategory>
<com.stardust.theme.preference.ThemeColorPreferenceCategory android:title="@string/text_advanced">
<com.afollestad.materialdialogs.prefs.MaterialListPreference
android:defaultValue="@string/key_single_thread"
android:entries="@array/run_mode_keys"
android:entryValues="@array/run_mode_values"
android:key="@string/key_run_mode"
android:summary="@string/summary_command_run_mode"
android:title="@string/text_command_run_mode"
/>
</com.stardust.theme.preference.ThemeColorPreferenceCategory>
<com.stardust.theme.preference.ThemeColorPreferenceCategory android:title="@string/text_about">
<Preference android:title="@string/text_check_update"/>
<Preference android:title="@string/text_issue_report"/>
<Preference android:title="@string/text_join_qq_group"/>
<Preference android:title="@string/text_about"/>
<Preference android:title="@string/text_licenses"/>

View File

@ -85,8 +85,7 @@ public abstract class JavaScriptEngineManager {
void removeEngine(JavaScriptEngine engine) {
synchronized (mEngines) {
mEngines.remove(engine);
if (mEngineLifecycleCallback != null) {
if (mEngines.remove(engine) && mEngineLifecycleCallback != null) {
mEngineLifecycleCallback.onEngineRemove(engine);
}
}

View File

@ -1,10 +1,10 @@
package com.stardust.autojs.engine;
import android.os.Looper;
import android.util.Log;
import com.stardust.autojs.rhino_android.AndroidContextFactory;
import com.stardust.autojs.rhino_android.RhinoAndroidHelper;
import com.stardust.autojs.runtime.ScriptRuntime;
import com.stardust.autojs.runtime.ScriptStopException;
import com.stardust.autojs.script.ScriptSource;
import com.stardust.view.accessibility.AccessibilityNodeInfoAllocator;
@ -17,7 +17,6 @@ import org.mozilla.javascript.ScriptableObject;
import java.io.File;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.Timer;
@ -36,6 +35,7 @@ public class RhinoJavaScriptEngine implements JavaScriptEngine {
private Thread mThread;
private RhinoJavaScriptEngineManager mEngineManager;
private Map<String, Object> mTags = new Hashtable<>();
private boolean mDestroyed = false;
public RhinoJavaScriptEngine(RhinoJavaScriptEngineManager engineManager) {
mEngineManager = engineManager;
@ -67,7 +67,7 @@ public class RhinoJavaScriptEngine implements JavaScriptEngine {
}
@Override
public void destroy() {
public synchronized void destroy() {
Context.exit();
// TODO: 2017/4/6 XXX :在这里回收内存池并不好
final AccessibilityNodeInfoAllocator allocator = (AccessibilityNodeInfoAllocator) getTag("allocator");
@ -75,6 +75,7 @@ public class RhinoJavaScriptEngine implements JavaScriptEngine {
new Timer().schedule(new TimerTask() {
@Override
public void run() {
// FIXME: 2017/4/28
//allocator.recycleAll();
}
}, 1000);
@ -136,14 +137,13 @@ public class RhinoJavaScriptEngine implements JavaScriptEngine {
@Override
protected void observeInstructionCount(Context cx, int instructionCount) {
if (Thread.currentThread().isInterrupted()) {
Context.exit();
throw new ScriptStopException(new InterruptedException());
}
}
@Override
protected Context makeContext() {
Context cx = super.makeContext();
cx.setInstructionObserverThreshold(10000);
return cx;

View File

@ -0,0 +1,19 @@
package com.stardust.autojs.runtime.api;
/**
* Created by Stardust on 2017/4/29.
*/
public class AutomatorConfig {
private static boolean isUnintendedGuardEnabled = false;
public static boolean isUnintendedGuardEnabled() {
return isUnintendedGuardEnabled;
}
public static void setIsUnintendedGuardEnabled(boolean isUnintendedGuardEnabled) {
AutomatorConfig.isUnintendedGuardEnabled = isUnintendedGuardEnabled;
}
}

View File

@ -2,6 +2,7 @@ package com.stardust.autojs.runtime.api;
import android.accessibilityservice.AccessibilityService;
import android.support.annotation.NonNull;
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
@ -87,7 +88,8 @@ public class UiSelector extends UiGlobalSelector {
@JavascriptInterface
public UiObjectCollection find() {
ensureAccessibilityServiceEnabled();
if (isRunningPackageSelf()) {
if (AutomatorConfig.isUnintendedGuardEnabled() && isRunningPackageSelf()) {
Log.d(TAG, "isSelfPackage return null");
return null;
}
AccessibilityService service = mAccessibilityBridge.getService();
@ -105,7 +107,7 @@ public class UiSelector extends UiGlobalSelector {
}
private boolean isRunningPackageSelf() {
return DeveloperUtils.isRunningPackageSelf(mAccessibilityBridge.getInfoProvider().getLatestPackage());
return DeveloperUtils.isSelfPackage(mAccessibilityBridge.getInfoProvider().getLatestPackage());
}
@ -115,6 +117,7 @@ public class UiSelector extends UiGlobalSelector {
UiObjectCollection uiObjectCollection;
do {
if (Thread.currentThread().isInterrupted()) {
Log.d(TAG, "Thread isInterrupted");
throw new ScriptStopException(new InterruptedException());
}
uiObjectCollection = find();

View File

@ -11,6 +11,7 @@ import android.view.accessibility.AccessibilityNodeInfo;
import com.stardust.autojs.runtime.AccessibilityBridge;
import com.stardust.autojs.runtime.JavascriptInterface;
import com.stardust.autojs.runtime.ScriptRuntime;
import com.stardust.autojs.runtime.api.AutomatorConfig;
import com.stardust.automator.AccessibilityEventCommandHost;
import com.stardust.automator.simple_action.SimpleAction;
import com.stardust.automator.simple_action.ActionFactory;
@ -24,6 +25,8 @@ import com.stardust.view.accessibility.AccessibilityNodeInfoAllocator;
public class SimpleActionAutomator {
private static final String TAG = "SimpleActionAutomator";
@Deprecated
private static class PerformGlobalActionCommand extends AccessibilityEventCommandHost.AbstractCommand {
@ -185,7 +188,8 @@ public class SimpleActionAutomator {
@SuppressWarnings("unchecked")
private boolean performAction(SimpleAction simpleAction) {
ensureAccessibilityServiceEnabled();
if (isRunningPackageSelf()) {
if (AutomatorConfig.isUnintendedGuardEnabled() && isRunningPackageSelf()) {
Log.i(TAG, "performAction: running package is self. return false");
return false;
}
AccessibilityService service = mAccessibilityBridge.getService();
@ -203,6 +207,6 @@ public class SimpleActionAutomator {
}
private boolean isRunningPackageSelf() {
return DeveloperUtils.isRunningPackageSelf(mAccessibilityBridge.getInfoProvider().getLatestPackage());
return DeveloperUtils.isSelfPackage(mAccessibilityBridge.getInfoProvider().getLatestPackage());
}
}

View File

@ -0,0 +1,29 @@
package com.stardust.pio;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
/**
* Created by Stardust on 2017/4/29.
*/
public class PRandomAccessBinaryFile extends RandomAccessFile {
private RandomAccessFile mRandomAccessFile;
public PRandomAccessBinaryFile(String name, String mode) throws FileNotFoundException {
super(name, mode);
}
public PRandomAccessBinaryFile(File file, String mode) throws FileNotFoundException {
super(file, mode);
}
public String readline() throws IOException {
return super.readLine();
}
}

View File

@ -16,7 +16,7 @@ public class DeveloperUtils {
}
}
public static boolean isRunningPackageSelf(@Nullable String runningPackage) {
public static boolean isSelfPackage(@Nullable String runningPackage) {
return PACKAGE_NAME.equals(runningPackage);
}
}