This commit is contained in:
hyb1996
2017-10-29 12:39:13 +08:00
37 changed files with 693 additions and 255 deletions

View File

@@ -9,8 +9,8 @@ android {
applicationId "com.stardust.scriptdroid" applicationId "com.stardust.scriptdroid"
minSdkVersion 17 minSdkVersion 17
targetSdkVersion 23 targetSdkVersion 23
versionCode 214 versionCode 215
versionName "3.0.0 Alpha15" versionName "3.0.0 Alpha16"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
multiDexEnabled true multiDexEnabled true
ndk { ndk {

View File

@@ -18,6 +18,7 @@ public class Pref {
private static final String KEY_SHOULD_SHOW_ANNUNCIATION = "Sing about all the things you forgot, things you are not"; private static final String KEY_SHOULD_SHOW_ANNUNCIATION = "Sing about all the things you forgot, things you are not";
private static final String KEY_FIRST_SHOW_AD = "En, Today is 17.7.7, but, I'm still love you so...."; private static final String KEY_FIRST_SHOW_AD = "En, Today is 17.7.7, but, I'm still love you so....";
private static final String KEY_LAST_SHOW_AD_MILLIS = "But... it seems that...you will not come back any more..."; private static final String KEY_LAST_SHOW_AD_MILLIS = "But... it seems that...you will not come back any more...";
private static final String KEY_FLOATING_MENU_SHOWN = "17.10.28 I have idea of what you think...maybe...I'm overthinking...";
private static SharedPreferences.OnSharedPreferenceChangeListener onSharedPreferenceChangeListener = new SharedPreferences.OnSharedPreferenceChangeListener() { private static SharedPreferences.OnSharedPreferenceChangeListener onSharedPreferenceChangeListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
@Override @Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
@@ -147,4 +148,12 @@ public class Pref {
public static String getDocumentationUrl() { public static String getDocumentationUrl() {
return "file:///android_asset/docs/"; return "file:///android_asset/docs/";
} }
public static boolean isFloatingMenuShown() {
return def().getBoolean(KEY_FLOATING_MENU_SHOWN, false);
}
public static void setFloatingMenuShown(boolean checked) {
def().edit().putBoolean(KEY_FLOATING_MENU_SHOWN, checked).apply();
}
} }

View File

@@ -0,0 +1,74 @@
package com.stardust.scriptdroid.io;
import android.content.Context;
import android.content.res.AssetManager;
import android.support.annotation.NonNull;
import com.stardust.pio.PFile;
import com.stardust.pio.PFiles;
import com.stardust.scriptdroid.model.script.ScriptFile;
import java.io.File;
import io.reactivex.Observable;
/**
* Created by Stardust on 2017/10/28.
*/
public class SampleFileProvider extends StorageFileProvider {
private AssetManager mAssetManager;
private Context mContext;
public SampleFileProvider(String path, Context context) {
super(path, 10);
mContext = context;
mAssetManager = context.getAssets();
}
public SampleFileProvider(Context context) {
this("sample/", context);
}
@Override
protected Observable<PFile> listFiles(PFile directory) {
return Observable.just(directory)
.flatMap(dir -> Observable.fromArray(mAssetManager.list(directory.getPath())))
.map(path -> {
String absPath = new File(directory, path).getPath();
if (!absPath.endsWith(".js")) {
return new AssetDirectory(absPath);
}
PFile file = new PFile(mContext.getFilesDir(), absPath);
if (!file.exists()) {
copySample(mContext, absPath, file.getPath());
}
return file;
});
}
public static boolean copySample(Context context, String samplePath, String pathTo) {
PFiles.ensureDir(pathTo);
return PFiles.copyAsset(context, samplePath, pathTo);
}
public static class AssetDirectory extends ScriptFile {
public AssetDirectory(@NonNull String pathname) {
super(pathname);
}
@Override
public boolean isDirectory() {
return true;
}
@Override
public boolean isFile() {
return false;
}
}
}

View File

@@ -16,9 +16,6 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import io.reactivex.Observable; import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.annotations.NonNull;
import io.reactivex.functions.Function;
/** /**
* Created by Stardust on 2017/3/31. * Created by Stardust on 2017/3/31.
@@ -82,6 +79,7 @@ public class StorageFileProvider {
private EventBus mDirectoryEventBus = new EventBus(); private EventBus mDirectoryEventBus = new EventBus();
private LimitedHashMap<String, List<PFile>> mPFileCache; private LimitedHashMap<String, List<PFile>> mPFileCache;
private PFile mInitialDirectory; private PFile mInitialDirectory;
private FileFilter mFileFilter;
public StorageFileProvider(PFile initialDirectory, int cacheSize, FileFilter fileFilter) { public StorageFileProvider(PFile initialDirectory, int cacheSize, FileFilter fileFilter) {
mInitialDirectory = initialDirectory; mInitialDirectory = initialDirectory;
@@ -89,7 +87,6 @@ public class StorageFileProvider {
mPFileCache = new LimitedHashMap<>(cacheSize); mPFileCache = new LimitedHashMap<>(cacheSize);
} }
private FileFilter mFileFilter;
public StorageFileProvider(String path, int cacheSize) { public StorageFileProvider(String path, int cacheSize) {
this(new PFile(path), cacheSize); this(new PFile(path), cacheSize);
@@ -185,11 +182,9 @@ public class StorageFileProvider {
} }
private Observable<PFile> listFiles(PFile directory) { protected Observable<PFile> listFiles(PFile directory) {
return Observable.just(directory) return Observable.just(directory)
.flatMap(new Function<PFile, ObservableSource<PFile>>() { .flatMap(dir -> {
@Override
public ObservableSource<PFile> apply(@NonNull PFile dir) throws Exception {
PFile[] files; PFile[] files;
if (mFileFilter == null) { if (mFileFilter == null) {
files = dir.listFiles(); files = dir.listFiles();
@@ -201,7 +196,6 @@ public class StorageFileProvider {
} }
mPFileCache.put(dir.getPath(), new ArrayList<>(Arrays.asList(files))); mPFileCache.put(dir.getPath(), new ArrayList<>(Arrays.asList(files)));
return Observable.fromArray(files); return Observable.fromArray(files);
}
}); });
} }

View File

@@ -1,18 +0,0 @@
package com.stardust.scriptdroid.model.sample;
import java.io.Serializable;
/**
* Created by Stardust on 2017/3/13.
*/
public class Sample implements Serializable {
public String name;
public String path;
public Sample(String name, String path) {
this.name = name;
this.path = path;
}
}

View File

@@ -0,0 +1,112 @@
package com.stardust.scriptdroid.model.sample;
import android.content.res.AssetManager;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.stardust.autojs.script.JavaScriptSource;
import com.stardust.autojs.script.ScriptSource;
import com.stardust.pio.PFiles;
import com.stardust.pio.UncheckedIOException;
import com.stardust.scriptdroid.model.script.ScriptFile;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
/**
* Created by Stardust on 2017/10/28.
*/
public class SampleFile extends ScriptFile {
private long mLength;
private AssetManager mAssetManager;
public SampleFile(@NonNull String pathname, AssetManager assetManager) {
super(pathname);
mAssetManager = assetManager;
init();
}
private void init() {
if (isDirectory()) {
mLength = 0;
return;
}
try {
InputStream inputStream = openInputStream();
mLength = inputStream.available();
inputStream.close();
} catch (IOException e) {
mLength = 0;
}
}
public SampleFile(String parent, @NonNull String child, AssetManager assetManager) {
super(parent, child);
mAssetManager = assetManager;
init();
}
public SampleFile(File parent, @NonNull String child, AssetManager assetManager) {
super(parent, child);
mAssetManager = assetManager;
init();
}
@Override
public boolean isFile() {
return getName().endsWith(".js");
}
@Override
public boolean isDirectory() {
return !isFile();
}
@Override
public long length() {
return mLength;
}
@Override
public String[] list() {
try {
return mAssetManager.list(getPath());
} catch (IOException e) {
return null;
}
}
@Override
public ScriptSource toSource() {
return new JavaScriptSource(getSimplifiedName()) {
@NonNull
@Override
public String getScript() {
try {
return PFiles.read(openInputStream());
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
@Nullable
@Override
public Reader getScriptReader() {
try {
return new InputStreamReader(openInputStream());
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
};
}
public InputStream openInputStream() throws IOException {
return mAssetManager.open(getPath());
}
}

View File

@@ -1,53 +0,0 @@
package com.stardust.scriptdroid.model.sample;
import android.content.Context;
import android.content.res.AssetManager;
import com.stardust.pio.PFiles;
import com.stardust.scriptdroid.App;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Stardust on 2017/1/30.
*/
public class SampleFileManager {
private static SampleFileManager instance = new SampleFileManager();
public static SampleFileManager getInstance() {
return instance;
}
private Context getContext() {
return App.getApp();
}
public List<SampleGroup> getSamplesFromAssets(AssetManager assets, String path) {
List<SampleGroup> sampleGroups = new ArrayList<>();
try {
String[] groups = assets.list(path);
for (String groupName : groups) {
sampleGroups.add(getSampleGroupFromAssets(assets, groupName, path + "/" + groupName));
}
return sampleGroups;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private SampleGroup getSampleGroupFromAssets(AssetManager assets, String groupName, String path) {
SampleGroup group = new SampleGroup(groupName);
try {
String[] samples = assets.list(path);
for (String sample : samples) {
group.add(new Sample(PFiles.getNameWithoutExtension(sample), path + "/" + sample));
}
return group;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}

View File

@@ -1,28 +0,0 @@
package com.stardust.scriptdroid.model.sample;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Stardust on 2017/3/13.
*/
public class SampleGroup {
public String name;
public List<Sample> sampleList;
public SampleGroup(String name) {
this(name, new ArrayList<Sample>());
}
public SampleGroup(String name, List<Sample> samples) {
this.name = name;
sampleList = samples;
}
public void add(Sample sample){
sampleList.add(sample);
}
}

View File

@@ -34,7 +34,7 @@ public class ScriptFile extends PFile {
super(parent, name); super(parent, name);
} }
public ScriptFile(ScriptFile parent, String child) { public ScriptFile(File parent, String child) {
super(parent, child); super(parent, child);
} }

View File

@@ -1,6 +1,5 @@
package com.stardust.scriptdroid.model.script; package com.stardust.scriptdroid.model.script;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
@@ -11,7 +10,6 @@ import com.stardust.autojs.execution.ScriptExecutionListener;
import com.stardust.autojs.execution.SimpleScriptExecutionListener; import com.stardust.autojs.execution.SimpleScriptExecutionListener;
import com.stardust.autojs.runtime.exception.ScriptInterruptedException; import com.stardust.autojs.runtime.exception.ScriptInterruptedException;
import com.stardust.autojs.script.ScriptSource; import com.stardust.autojs.script.ScriptSource;
import com.stardust.autojs.script.StringScriptSource;
import com.stardust.scriptdroid.App; import com.stardust.scriptdroid.App;
import com.stardust.scriptdroid.R; import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.autojs.AutoJs; import com.stardust.scriptdroid.autojs.AutoJs;
@@ -19,9 +17,7 @@ import com.stardust.scriptdroid.external.CommonUtils;
import com.stardust.scriptdroid.external.shortcut.Shortcut; import com.stardust.scriptdroid.external.shortcut.Shortcut;
import com.stardust.scriptdroid.external.shortcut.ShortcutActivity; import com.stardust.scriptdroid.external.shortcut.ShortcutActivity;
import com.stardust.scriptdroid.io.StorageFileProvider; import com.stardust.scriptdroid.io.StorageFileProvider;
import com.stardust.scriptdroid.model.sample.Sample;
import com.stardust.scriptdroid.ui.edit.EditActivity; import com.stardust.scriptdroid.ui.edit.EditActivity;
import com.stardust.util.AssetsCache;
import org.mozilla.javascript.RhinoException; import org.mozilla.javascript.RhinoException;
@@ -113,10 +109,6 @@ public class Scripts {
new ExecutionConfig().path(directoryPath, StorageFileProvider.DEFAULT_DIRECTORY_PATH)); new ExecutionConfig().path(directoryPath, StorageFileProvider.DEFAULT_DIRECTORY_PATH));
} }
public static ScriptExecution run(Context context, Sample file) {
ScriptSource source = new StringScriptSource(file.name, AssetsCache.get(context.getAssets(), file.path));
return AutoJs.getInstance().getScriptEngineService().execute(source);
}
public static ScriptExecution runWithBroadcastSender(ScriptSource source) { public static ScriptExecution runWithBroadcastSender(ScriptSource source) {
return AutoJs.getInstance().getScriptEngineService().execute(source, BROADCAST_SENDER_SCRIPT_EXECUTION_LISTENER, return AutoJs.getInstance().getScriptEngineService().execute(source, BROADCAST_SENDER_SCRIPT_EXECUTION_LISTENER,

View File

@@ -22,10 +22,10 @@ import com.stardust.pio.UncheckedIOException;
import com.stardust.scriptdroid.App; import com.stardust.scriptdroid.App;
import com.stardust.scriptdroid.R; import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.io.TmpScriptFiles; import com.stardust.scriptdroid.io.TmpScriptFiles;
import com.stardust.scriptdroid.model.sample.SampleFile;
import com.stardust.scriptdroid.model.script.ScriptFile; import com.stardust.scriptdroid.model.script.ScriptFile;
import com.stardust.scriptdroid.model.script.Scripts; import com.stardust.scriptdroid.model.script.Scripts;
import com.stardust.scriptdroid.io.StorageFileProvider; import com.stardust.scriptdroid.io.StorageFileProvider;
import com.stardust.scriptdroid.model.sample.Sample;
import com.stardust.scriptdroid.network.download.DownloadManager; import com.stardust.scriptdroid.network.download.DownloadManager;
import com.stardust.scriptdroid.ui.filechooser.FileChooserDialogBuilder; import com.stardust.scriptdroid.ui.filechooser.FileChooserDialogBuilder;
import com.stardust.scriptdroid.ui.shortcut.ShortcutCreateActivity; import com.stardust.scriptdroid.ui.shortcut.ShortcutCreateActivity;
@@ -110,10 +110,8 @@ public class ScriptOperations {
public Observable<String> importFile(final String pathFrom) { public Observable<String> importFile(final String pathFrom) {
return showFileNameInputDialog(PFiles.getNameWithoutExtension(pathFrom), PFiles.getExtension(pathFrom)) return showFileNameInputDialog(PFiles.getNameWithoutExtension(pathFrom), PFiles.getExtension(pathFrom))
.observeOn(Schedulers.io()) .observeOn(Schedulers.io())
.map(new Function<String, String>() { .map(input -> {
@Override final String pathTo = getCurrentDirectoryPath() + input + "." + PFiles.getExtension(pathFrom);
public String apply(@io.reactivex.annotations.NonNull String s) throws Exception {
final String pathTo = getCurrentDirectoryPath() + s + "." + PFiles.getExtension(pathFrom);
if (PFiles.copy(pathFrom, pathTo)) { if (PFiles.copy(pathFrom, pathTo)) {
showMessage(R.string.text_import_succeed); showMessage(R.string.text_import_succeed);
} else { } else {
@@ -121,17 +119,14 @@ public class ScriptOperations {
} }
mStorageFileProvider.notifyFileCreated(mCurrentDirectory, new ScriptFile(pathTo)); mStorageFileProvider.notifyFileCreated(mCurrentDirectory, new ScriptFile(pathTo));
return pathTo; return pathTo;
}
}); });
} }
public Observable<String> importFile(String prefix, final InputStream inputStream, final String ext) { public Observable<String> importFile(String prefix, final InputStream inputStream, final String ext) {
return showFileNameInputDialog(PFiles.getNameWithoutExtension(prefix), ext) return showFileNameInputDialog(PFiles.getNameWithoutExtension(prefix), ext)
.observeOn(Schedulers.io()) .observeOn(Schedulers.io())
.map(new Function<String, String>() { .map(input -> {
@Override final String pathTo = getCurrentDirectoryPath() + input + "." + ext;
public String apply(@io.reactivex.annotations.NonNull String s) throws Exception {
final String pathTo = getCurrentDirectoryPath() + s + "." + ext;
if (PFiles.copyStream(inputStream, pathTo)) { if (PFiles.copyStream(inputStream, pathTo)) {
showMessage(R.string.text_import_succeed); showMessage(R.string.text_import_succeed);
} else { } else {
@@ -139,23 +134,20 @@ public class ScriptOperations {
} }
mStorageFileProvider.notifyFileCreated(mCurrentDirectory, new ScriptFile(pathTo)); mStorageFileProvider.notifyFileCreated(mCurrentDirectory, new ScriptFile(pathTo));
return pathTo; return pathTo;
}
}); });
} }
public void newDirectory() { public void newDirectory() {
showNameInputDialog("", new InputCallback()) showNameInputDialog("", new InputCallback())
.subscribe(new Consumer<String>() { .subscribe(path -> {
@Override ScriptFile newDir = new ScriptFile(getCurrentDirectory(), path);
public void accept(@io.reactivex.annotations.NonNull String path) throws Exception { if (newDir.mkdirs()) {
if (new ScriptFile(getCurrentDirectory(), path).mkdirs()) {
showMessage(R.string.text_already_create); showMessage(R.string.text_already_create);
mStorageFileProvider.notifyFileCreated(mCurrentDirectory, new ScriptFile(path)); mStorageFileProvider.notifyFileCreated(mCurrentDirectory, new ScriptFile(newDir));
} else { } else {
showMessage(R.string.text_create_fail); showMessage(R.string.text_create_fail);
} }
}
}); });
} }
@@ -164,12 +156,7 @@ public class ScriptOperations {
showMessageWithoutThreadSwitch(resId); showMessageWithoutThreadSwitch(resId);
} }
//switch to ui thread to show message //switch to ui thread to show message
App.getApp().getUiHandler().post(new Runnable() { App.getApp().getUiHandler().post(() -> showMessageWithoutThreadSwitch(resId));
@Override
public void run() {
showMessageWithoutThreadSwitch(resId);
}
});
} }
private void showMessageWithoutThreadSwitch(int resId) { private void showMessageWithoutThreadSwitch(int resId) {
@@ -191,12 +178,9 @@ public class ScriptOperations {
.inputType(InputType.TYPE_CLASS_TEXT) .inputType(InputType.TYPE_CLASS_TEXT)
.alwaysCallInputCallback() .alwaysCallInputCallback()
.input(getString(R.string.text_please_input_name), prefix, false, textWatcher) .input(getString(R.string.text_please_input_name), prefix, false, textWatcher)
.onPositive(new MaterialDialog.SingleButtonCallback() { .onPositive((dialog, which) -> {
@Override
public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
input.onNext(dialog.getInputEditText().getText().toString()); input.onNext(dialog.getInputEditText().getText().toString());
input.onComplete(); input.onComplete();
}
}) })
.build()); .build());
return input; return input;
@@ -207,9 +191,9 @@ public class ScriptOperations {
return mContext.getString(resId); return mContext.getString(resId);
} }
public Observable<String> importSample(Sample sample) { public Observable<String> importSample(SampleFile sample) {
try { try {
return importFile(sample.name, mContext.getAssets().open(sample.path), PFiles.getExtension(sample.path)); return importFile(sample.getSimplifiedName(), sample.openInputStream(), sample.getExtension());
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
showMessage(R.string.text_import_fail); showMessage(R.string.text_import_fail);

View File

@@ -17,6 +17,7 @@ import android.webkit.WebSettings;
import android.webkit.WebView; import android.webkit.WebView;
import android.webkit.WebViewClient; import android.webkit.WebViewClient;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import android.widget.Toast;
import com.afollestad.materialdialogs.DialogAction; import com.afollestad.materialdialogs.DialogAction;
import com.afollestad.materialdialogs.MaterialDialog; import com.afollestad.materialdialogs.MaterialDialog;
@@ -172,46 +173,36 @@ public class CodeMirrorEditor extends FrameLayout {
mWebView.setWebChromeClient(new MyWebChromeClient()); mWebView.setWebChromeClient(new MyWebChromeClient());
} }
public void setReadOnly(boolean readOnly) {
evalJavaScript(String.format("editor.setOption('readOnly', %b);", readOnly));
}
public void setProgress(boolean onProgress) { public void setProgress(boolean onProgress) {
mProgressBarContainer.setVisibility(onProgress ? VISIBLE : GONE); mProgressBarContainer.setVisibility(onProgress ? VISIBLE : GONE);
} }
public void setText(final String text) { public void setText(final String text) {
mTextFromAndroid = text; mTextFromAndroid = text;
mPageFinished.promise().done(new DoneCallback<Void>() { mPageFinished.promise().done(result -> evalJavaScript("editor.setValue(__bridge__.getStringFromAndroid());"));
@Override
public void onDone(Void result) {
evalJavaScript("editor.setValue(__bridge__.getStringFromAndroid());");
}
});
} }
public void insert(String text) { public void insert(String text) {
mTextFromAndroid = text; mTextFromAndroid = text;
mPageFinished.promise().done(new DoneCallback<Void>() { mPageFinished.promise().done(result -> evalJavaScript("editor.replaceSelection(__bridge__.getStringFromAndroid());"));
@Override
public void onDone(Void result) {
evalJavaScript("editor.replaceSelection(__bridge__.getStringFromAndroid());");
}
});
} }
public void loadFile(final File file) { public void loadFile(final File file) {
setProgress(true); setProgress(true);
// TODO: 2017/9/29 handle error Observable.fromCallable(() -> PFiles.read(file))
Observable.fromCallable(new Callable<String>() { .subscribeOn(Schedulers.io())
@Override
public String call() throws Exception {
return PFiles.read(file);
}
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<String>() { .subscribe(s -> {
@Override
public void accept(@NonNull String s) throws Exception {
setText(s); setText(s);
setProgress(false); setProgress(false);
} }, err -> {
err.printStackTrace();
Toast.makeText(getContext(), getContext().getString(R.string.text_cannot_read_file, file.getPath()),
Toast.LENGTH_SHORT).show();
}); });
} }

View File

@@ -14,8 +14,10 @@ import org.androidannotations.annotations.AfterViews;
import org.androidannotations.annotations.EActivity; import org.androidannotations.annotations.EActivity;
import org.androidannotations.annotations.ViewById; import org.androidannotations.annotations.ViewById;
import static com.stardust.scriptdroid.ui.edit.EditorView.EXTRA_CONTENT;
import static com.stardust.scriptdroid.ui.edit.EditorView.EXTRA_NAME; import static com.stardust.scriptdroid.ui.edit.EditorView.EXTRA_NAME;
import static com.stardust.scriptdroid.ui.edit.EditorView.EXTRA_PATH; import static com.stardust.scriptdroid.ui.edit.EditorView.EXTRA_PATH;
import static com.stardust.scriptdroid.ui.edit.EditorView.EXTRA_READ_ONLY;
/** /**
* Created by Stardust on 2017/1/29. * Created by Stardust on 2017/1/29.
@@ -41,8 +43,12 @@ public class EditActivity extends BaseActivity {
.putExtra(EXTRA_NAME, name)); .putExtra(EXTRA_NAME, name));
} }
public static void editFile(Context context, ScriptFile file) { public static void viewContent(Context context, String name, String content) {
editFile(context, file.getSimplifiedName(), file.getPath()); context.startActivity(new Intent(context, EditActivity_.class)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.putExtra(EXTRA_CONTENT, content)
.putExtra(EXTRA_NAME, name)
.putExtra(EXTRA_READ_ONLY, true));
} }
@AfterViews @AfterViews

View File

@@ -151,6 +151,9 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
if (!intent.getBooleanExtra(EXTRA_RUN_ENABLED, true)) { if (!intent.getBooleanExtra(EXTRA_RUN_ENABLED, true)) {
findViewById(R.id.run).setVisibility(GONE); findViewById(R.id.run).setVisibility(GONE);
} }
if(mReadOnly){
mEditor.setReadOnly(true);
}
} }

View File

@@ -17,7 +17,7 @@ import com.stardust.autojs.engine.JavaScriptEngine;
import com.stardust.autojs.execution.ScriptExecution; import com.stardust.autojs.execution.ScriptExecution;
import com.stardust.scriptdroid.R; import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.autojs.AutoJs; import com.stardust.scriptdroid.autojs.AutoJs;
import com.stardust.scriptdroid.model.sample.Sample; import com.stardust.scriptdroid.model.sample.SampleFile;
import com.stardust.scriptdroid.ui.BaseActivity; import com.stardust.scriptdroid.ui.BaseActivity;
import com.stardust.scriptdroid.ui.common.ScriptOperations; import com.stardust.scriptdroid.ui.common.ScriptOperations;
import com.stardust.theme.ThemeColorManager; import com.stardust.theme.ThemeColorManager;
@@ -41,14 +41,14 @@ import static com.stardust.scriptdroid.model.script.Scripts.EXTRA_EXCEPTION_MESS
public class ViewSampleActivity extends AppCompatActivity implements OnActivityResultDelegate.DelegateHost { public class ViewSampleActivity extends AppCompatActivity implements OnActivityResultDelegate.DelegateHost {
public static void view(Context context, Sample sample) { public static void view(Context context, SampleFile sample) {
context.startActivity(new Intent(context, ViewSampleActivity.class) context.startActivity(new Intent(context, ViewSampleActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.putExtra("sample", sample)); .putExtra("sample_path", sample.getPath()));
} }
private View mView; private View mView;
private Sample mSample; private SampleFile mSample;
private ScriptExecution mScriptExecution; private ScriptExecution mScriptExecution;
private SparseArray<ToolbarMenuItem> mMenuMap; private SparseArray<ToolbarMenuItem> mMenuMap;
private OnActivityResultDelegate.Mediator mMediator = new OnActivityResultDelegate.Mediator(); private OnActivityResultDelegate.Mediator mMediator = new OnActivityResultDelegate.Mediator();
@@ -76,8 +76,7 @@ public class ViewSampleActivity extends AppCompatActivity implements OnActivityR
} }
private void handleIntent(Intent intent) { private void handleIntent(Intent intent) {
mSample = (Sample) intent.getSerializableExtra("sample"); mSample = new SampleFile(intent.getStringExtra("sample_path"), getAssets());
String content = AssetsCache.get(this, mSample.path);
} }
private void setUpUI() { private void setUpUI() {
@@ -92,7 +91,7 @@ public class ViewSampleActivity extends AppCompatActivity implements OnActivityR
} }
private void setUpToolbar() { private void setUpToolbar() {
BaseActivity.setToolbarAsBack(this, R.id.toolbar, mSample.name); BaseActivity.setToolbarAsBack(this, R.id.toolbar, mSample.getSimplifiedName());
} }
@OnClick(R.id.run) @OnClick(R.id.run)

View File

@@ -246,7 +246,7 @@ public class CircularMenu implements Recorder.OnStateChangedListener {
} }
@Optional @Optional
@OnClick(R.id.package_name) @OnClick(R.id.class_name)
void copyActivityName() { void copyActivityName() {
dismissSettingsDialog(); dismissSettingsDialog();
if (TextUtils.isEmpty(mRunningActivity)) if (TextUtils.isEmpty(mRunningActivity))

View File

@@ -162,9 +162,7 @@ public class LayoutHierarchyView extends MultiLevelListView {
Stack<NodeInfo> parents = new Stack<>(); Stack<NodeInfo> parents = new Stack<>();
searchNodeParents(selectedNode, mRootNode, parents); searchNodeParents(selectedNode, mRootNode, parents);
mClickedNodeInfo = parents.peek(); mClickedNodeInfo = parents.peek();
for (NodeInfo nodeInfo : parents) { mInitiallyExpandedNodes.addAll(parents);
mInitiallyExpandedNodes.add(nodeInfo);
}
mAdapter.reloadData(); mAdapter.reloadData();
} }
@@ -225,7 +223,7 @@ public class LayoutHierarchyView extends MultiLevelListView {
NodeInfo nodeInfo = (NodeInfo) object; NodeInfo nodeInfo = (NodeInfo) object;
ViewHolder viewHolder; ViewHolder viewHolder;
if (convertView == null) { if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.layout_hierarchy_view_item, LayoutHierarchyView.this, false); convertView = LayoutInflater.from(getContext()).inflate(R.layout.layout_hierarchy_view_item, null);
viewHolder = new ViewHolder(convertView); viewHolder = new ViewHolder(convertView);
convertView.setTag(viewHolder); convertView.setTag(viewHolder);
} else { } else {

View File

@@ -31,6 +31,8 @@ import com.stardust.scriptdroid.ui.doc.OnlineDocsFragment_;
import com.stardust.scriptdroid.ui.floating.FloatyWindowManger; import com.stardust.scriptdroid.ui.floating.FloatyWindowManger;
import com.stardust.scriptdroid.io.StorageFileProvider; import com.stardust.scriptdroid.io.StorageFileProvider;
import com.stardust.scriptdroid.ui.main.community.CommunityFragment_; import com.stardust.scriptdroid.ui.main.community.CommunityFragment_;
import com.stardust.scriptdroid.ui.main.sample.SampleListFragment;
import com.stardust.scriptdroid.ui.main.sample.SampleListFragment_;
import com.stardust.scriptdroid.ui.main.scripts.MyScriptListFragment_; import com.stardust.scriptdroid.ui.main.scripts.MyScriptListFragment_;
import com.stardust.scriptdroid.ui.main.task.TaskManagerFragment_; import com.stardust.scriptdroid.ui.main.task.TaskManagerFragment_;
import com.stardust.theme.ThemeColorManager; import com.stardust.theme.ThemeColorManager;
@@ -145,6 +147,7 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega
.add(new MyScriptListFragment_(), R.string.text_script) .add(new MyScriptListFragment_(), R.string.text_script)
.add(new OnlineDocsFragment_(), R.string.text_tutorial) .add(new OnlineDocsFragment_(), R.string.text_tutorial)
.add(new CommunityFragment_(), R.string.text_community) .add(new CommunityFragment_(), R.string.text_community)
.add(new SampleListFragment_(), R.string.text_sample)
.add(new TaskManagerFragment_(), R.string.text_manage) .add(new TaskManagerFragment_(), R.string.text_manage)
.build(); .build();
mViewPager.setAdapter(mPagerAdapter); mViewPager.setAdapter(mPagerAdapter);
@@ -184,10 +187,10 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega
@Click(R.id.exit) @Click(R.id.exit)
public void exitCompletely() { public void exitCompletely() {
finish();
FloatyWindowManger.hideCircularMenu(); FloatyWindowManger.hideCircularMenu();
stopService(new Intent(this, FloatyService.class)); stopService(new Intent(this, FloatyService.class));
AutoJs.getInstance().getScriptEngineService().stopAll(); AutoJs.getInstance().getScriptEngineService().stopAll();
finish();
} }
@Override @Override

View File

@@ -89,7 +89,6 @@ public class DrawerFragment extends android.support.v4.app.Fragment {
@ViewById(R.id.default_cover) @ViewById(R.id.default_cover)
View mDefaultCover; View mDefaultCover;
private Disposable mConnectionStateDisposable; private Disposable mConnectionStateDisposable;
@@ -101,6 +100,7 @@ public class DrawerFragment extends android.support.v4.app.Fragment {
.doOnNext(connected -> mConnectionItem.getSwitchCompat().setChecked(connected)) .doOnNext(connected -> mConnectionItem.getSwitchCompat().setChecked(connected))
.subscribe(); .subscribe();
EventBus.getDefault().register(this); EventBus.getDefault().register(this);
} }
@Override @Override
@@ -118,6 +118,9 @@ public class DrawerFragment extends android.support.v4.app.Fragment {
@AfterViews @AfterViews
void setUpViews() { void setUpViews() {
ThemeColorManager.addViewBackground(mHeaderView); ThemeColorManager.addViewBackground(mHeaderView);
if (Pref.isFloatingMenuShown()) {
mFloatingWindowItem.getSwitchCompat().setChecked(true);
}
} }
private void syncUserInfo() { private void syncUserInfo() {
@@ -204,6 +207,9 @@ public class DrawerFragment extends android.support.v4.app.Fragment {
void showOrDismissFloatingWindow() { void showOrDismissFloatingWindow() {
boolean isFloatingWindowShowing = FloatyWindowManger.isCircularMenuShowing(); boolean isFloatingWindowShowing = FloatyWindowManger.isCircularMenuShowing();
boolean checked = mFloatingWindowItem.getSwitchCompat().isChecked(); boolean checked = mFloatingWindowItem.getSwitchCompat().isChecked();
if (getActivity() != null && !getActivity().isFinishing()) {
Pref.setFloatingMenuShown(checked);
}
if (checked && !isFloatingWindowShowing) { if (checked && !isFloatingWindowShowing) {
FloatyWindowManger.showCircularMenu(); FloatyWindowManger.showCircularMenu();
enableAccessibilityServiceByRootIfNeeded(); enableAccessibilityServiceByRootIfNeeded();

View File

@@ -0,0 +1,108 @@
package com.stardust.scriptdroid.ui.main.sample;
import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.FloatingActionButton;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.io.SampleFileProvider;
import com.stardust.scriptdroid.io.StorageFileProvider;
import com.stardust.scriptdroid.model.script.Scripts;
import com.stardust.scriptdroid.tool.SimpleObserver;
import com.stardust.scriptdroid.ui.common.ScriptOperations;
import com.stardust.scriptdroid.ui.main.FloatingActionMenu;
import com.stardust.scriptdroid.ui.main.QueryEvent;
import com.stardust.scriptdroid.ui.main.ViewPagerFragment;
import com.stardust.scriptdroid.ui.main.scripts.ScriptListView;
import com.stardust.util.BackPressedHandler;
import org.androidannotations.annotations.AfterViews;
import org.androidannotations.annotations.EFragment;
import org.androidannotations.annotations.ViewById;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import io.reactivex.android.schedulers.AndroidSchedulers;
/**
* Created by Stardust on 2017/10/28.
*/
@EFragment(R.layout.fragment_sample_list)
public class SampleListFragment extends ViewPagerFragment implements BackPressedHandler {
public SampleListFragment() {
super(ROTATION_GONE);
}
@ViewById(R.id.sample_list)
ScriptListView mScriptFileList;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EventBus.getDefault().register(this);
}
@AfterViews
void setUpViews() {
mScriptFileList.setDirectorySpanSize(2);
mScriptFileList.setStorageFileProvider(new SampleFileProvider(getContext()));
mScriptFileList.setOnScriptFileClickListener((view, file) -> Scripts.edit(file));
}
@Override
public void onResume() {
super.onResume();
((BackPressedHandler.HostActivity) getActivity())
.getBackPressedObserver()
.registerHandlerAtFront(this);
}
@Override
public void onPause() {
super.onPause();
((BackPressedHandler.HostActivity) getActivity())
.getBackPressedObserver()
.unregisterHandler(this);
}
@Override
protected void onFabClick(FloatingActionButton fab) {
}
@Override
public boolean onBackPressed(Activity activity) {
if (mScriptFileList.canGoBack()) {
mScriptFileList.goBack();
return true;
}
return false;
}
@Subscribe
public void onQuerySummit(QueryEvent event) {
if (!isShown()) {
return;
}
if (event == QueryEvent.CLEAR) {
mScriptFileList.setFilter(null);
return;
}
String query = event.getQuery();
mScriptFileList.setFilter((file -> file.getSimplifiedName().contains(query)));
}
@Override
public void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
}

View File

@@ -0,0 +1,149 @@
package com.stardust.scriptdroid.ui.main.sample;
import android.content.Context;
import android.graphics.drawable.GradientDrawable;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.support.v4.content.res.ResourcesCompat;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.PopupMenu;
import android.widget.TextView;
import com.stardust.pio.PFiles;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.io.SampleFileProvider;
import com.stardust.scriptdroid.io.StorageFileProvider;
import com.stardust.scriptdroid.model.script.ScriptFile;
import com.stardust.scriptdroid.model.script.Scripts;
import com.stardust.scriptdroid.ui.common.ScriptOperations;
import com.stardust.scriptdroid.ui.main.scripts.ScriptListView;
import com.stardust.scriptdroid.ui.widget.BindableViewHolder;
import java.io.File;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
/**
* Created by Stardust on 2017/10/28.
*/
public class SampleListView extends ScriptListView {
public SampleListView(Context context) {
super(context);
}
public SampleListView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.copy_to_my_script:
new ScriptOperations(getContext(), this)
.importFile(mSelectedScriptFile.getPath())
.subscribe();
return true;
case R.id.reset:
resetSample();
return true;
default:
return super.onMenuItemClick(item);
}
}
private void resetSample() {
String samplePath = new File(getCurrentDirectory(), mSelectedScriptFile.getName()).getPath();
if (SampleFileProvider.copySample(getContext(), samplePath, mSelectedScriptFile.getPath())) {
Snackbar.make(this, R.string.text_reset_succeed, Snackbar.LENGTH_SHORT).show();
} else {
Snackbar.make(this, R.string.text_reset_fail, Snackbar.LENGTH_SHORT).show();
}
}
@Override
protected BindableViewHolder<?> onCreateViewHolder(LayoutInflater inflater, ViewGroup parent, int viewType) {
if (viewType == VIEW_TYPE_FILE) {
return new SampleFileViewHolder(inflater.inflate(R.layout.script_file_list_file, parent, false));
} else if (viewType == VIEW_TYPE_DIRECTORY) {
DirectoryViewHolder viewHolder = (DirectoryViewHolder) super.onCreateViewHolder(inflater, parent, viewType);
viewHolder.mOptions.setVisibility(GONE);
return viewHolder;
}
return super.onCreateViewHolder(inflater, parent, viewType);
}
class SampleFileViewHolder extends BindableViewHolder<ScriptFile> {
@BindView(R.id.name)
TextView mName;
@BindView(R.id.first_char)
TextView mFirstChar;
@BindView(R.id.desc)
TextView mDesc;
@BindView(R.id.more)
View mOptions;
@BindView(R.id.edit)
View mEdit;
GradientDrawable mFirstCharBackground;
private ScriptFile mScriptFile;
SampleFileViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
mFirstCharBackground = (GradientDrawable) mFirstChar.getBackground();
}
@Override
public void bind(ScriptFile file, int position) {
mScriptFile = file;
mName.setText(file.getSimplifiedName());
mDesc.setText(PFiles.getHumanReadableSize(file.length()));
if (file.getType() == ScriptFile.TYPE_JAVA_SCRIPT) {
mFirstChar.setText("J");
mFirstCharBackground.setColor(ResourcesCompat.getColor(getResources(), R.color.color_j, getContext().getTheme()));
mEdit.setVisibility(VISIBLE);
} else {
mFirstChar.setText("R");
mFirstCharBackground.setColor(ResourcesCompat.getColor(getResources(), R.color.color_r, getContext().getTheme()));
mEdit.setVisibility(GONE);
}
}
@OnClick(R.id.item)
void onItemClick() {
if (mOnScriptFileClickListener != null) {
mOnScriptFileClickListener.onScriptFileClick(itemView, mScriptFile);
}
notifyOperated();
}
@OnClick(R.id.run)
void run() {
Scripts.run(mScriptFile);
notifyOperated();
}
@OnClick(R.id.edit)
void edit() {
Scripts.edit(mScriptFile);
notifyOperated();
}
@OnClick(R.id.more)
void showOptionMenu() {
mSelectedScriptFile = mScriptFile;
PopupMenu popupMenu = new PopupMenu(getContext(), mOptions);
popupMenu.inflate(R.menu.menu_sample_options);
popupMenu.setOnMenuItemClickListener(SampleListView.this);
popupMenu.show();
}
}
}

View File

@@ -66,10 +66,10 @@ public class ScriptListView extends SwipeRefreshLayout implements SwipeRefreshLa
private RecyclerView mScriptListView; private RecyclerView mScriptListView;
private ScriptListAdapter mScriptListAdapter = new ScriptListAdapter(); private ScriptListAdapter mScriptListAdapter = new ScriptListAdapter();
private ScriptFile mCurrentDirectory; private ScriptFile mCurrentDirectory;
private OnScriptFileClickListener mOnScriptFileClickListener; protected OnScriptFileClickListener mOnScriptFileClickListener;
private Function<PFile, Boolean> mFilter; private Function<PFile, Boolean> mFilter;
private OnItemOperatedListener mOnItemOperatedListener; private OnItemOperatedListener mOnItemOperatedListener;
private ScriptFile mSelectedScriptFile; protected ScriptFile mSelectedScriptFile;
private StorageFileProvider mStorageFileProvider; private StorageFileProvider mStorageFileProvider;
private boolean mDirSortMenuShowing = false; private boolean mDirSortMenuShowing = false;
private boolean mDirsCollapsed; private boolean mDirsCollapsed;
@@ -174,9 +174,13 @@ public class ScriptListView extends SwipeRefreshLayout implements SwipeRefreshLa
mStorageFileProvider.getDirectoryFiles(mCurrentDirectory) mStorageFileProvider.getDirectoryFiles(mCurrentDirectory)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.filter(f -> mFilter == null ? true : mFilter.apply(f)) .filter(f -> mFilter == null ? true : mFilter.apply(f))
.collectInto(mScriptList.cloneConfig(), (list, file) -> .collectInto(mScriptList.cloneConfig(), (list, file) -> {
list.add(new ScriptFile(file)) if (file instanceof ScriptFile) {
) list.add((ScriptFile) file);
} else {
list.add(new ScriptFile(file));
}
})
.observeOn(Schedulers.computation()) .observeOn(Schedulers.computation())
.doOnSuccess(ScriptList::sort) .doOnSuccess(ScriptList::sort)
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
@@ -248,7 +252,7 @@ public class ScriptListView extends SwipeRefreshLayout implements SwipeRefreshLa
return true; return true;
} }
private void notifyOperated() { protected void notifyOperated() {
if (mOnItemOperatedListener != null) { if (mOnItemOperatedListener != null) {
mOnItemOperatedListener.OnItemOperated(mSelectedScriptFile); mOnItemOperatedListener.OnItemOperated(mSelectedScriptFile);
} }
@@ -345,7 +349,7 @@ public class ScriptListView extends SwipeRefreshLayout implements SwipeRefreshLa
} }
} }
class ScriptFileViewHolder extends BindableViewHolder<ScriptFile> { protected class ScriptFileViewHolder extends BindableViewHolder<ScriptFile> {
@BindView(R.id.name) @BindView(R.id.name)
@@ -413,12 +417,12 @@ public class ScriptListView extends SwipeRefreshLayout implements SwipeRefreshLa
} }
} }
class DirectoryViewHolder extends BindableViewHolder<ScriptFile> { protected class DirectoryViewHolder extends BindableViewHolder<ScriptFile> {
@BindView(R.id.name) @BindView(R.id.name)
TextView mName; public TextView mName;
@BindView(R.id.more) @BindView(R.id.more)
View mOptions; public View mOptions;
private ScriptFile mScriptFile; private ScriptFile mScriptFile;

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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">
<com.stardust.scriptdroid.ui.main.sample.SampleListView
android:id="@+id/sample_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</FrameLayout>

View File

@@ -5,12 +5,12 @@
android:id="@+id/item" android:id="@+id/item"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="2dp" android:layout_marginLeft="3dp"
android:layout_marginRight="2dp" android:layout_marginRight="3dp"
android:clickable="true" android:clickable="true"
android:foreground="?selectableItemBackground" android:foreground="?selectableItemBackground"
app:cardBackgroundColor="#ffffff" app:cardBackgroundColor="#ffffff"
app:cardElevation="1dp" app:cardElevation="0.5dp"
app:cardUseCompatPadding="true"> app:cardUseCompatPadding="true">
<LinearLayout <LinearLayout

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/run_repeatedly"
android:title="@string/text_run_repeatedly"/>
<item
android:id="@+id/floating_edit"
android:title="@string/text_floating_edit"/>
<item
android:id="@+id/create_shortcut"
android:title="@string/text_send_shortcut"/>
<item
android:id="@+id/copy_to_my_script"
android:title="@string/text_copy_to_my_script"/>
<item
android:id="@+id/reset"
android:title="@string/text_reset_to_initial_content"/>
</menu>

View File

@@ -275,6 +275,12 @@
<string name="text_registering">注册中</string> <string name="text_registering">注册中</string>
<string name="text_register_fail">注册失败</string> <string name="text_register_fail">注册失败</string>
<string name="text_register_succeed">注册成功</string> <string name="text_register_succeed">注册成功</string>
<string name="text_sample">示例</string>
<string name="text_copy_to_my_script">导入到我的脚本</string>
<string name="text_reset_to_initial_content">重置为初始内容</string>
<string name="text_reset_fail">重置失败</string>
<string name="text_reset_succeed">重置成功</string>
<string name="text_cannot_read_file" formatted="true">无法读取文件: %s</string>
<string-array name="ad_showing_mode_keys"> <string-array name="ad_showing_mode_keys">

View File

@@ -27,6 +27,7 @@ repositories {
flatDir { flatDir {
dirs 'libs' dirs 'libs'
} }
google()
} }
dependencies { dependencies {
@@ -41,8 +42,8 @@ dependencies {
compile('com.afollestad.material-dialogs:core:0.9.2.3', { compile('com.afollestad.material-dialogs:core:0.9.2.3', {
exclude group: 'com.android.support' exclude group: 'com.android.support'
}) })
compile 'com.android.support:design:25.3.1' compile 'com.android.support:design:25.4.0'
compile 'com.android.support:appcompat-v7:25.3.1' compile 'com.android.support:appcompat-v7:25.4.0'
compile 'com.github.hyb1996:EnhancedFloaty:0.17' compile 'com.github.hyb1996:EnhancedFloaty:0.17'
// Terminal emulator // Terminal emulator
compile(name: 'libtermexec-release', ext: 'aar') compile(name: 'libtermexec-release', ext: 'aar')

View File

@@ -65,7 +65,7 @@ public class StardustConsole extends AbstractConsole {
private AtomicInteger mIdCounter = new AtomicInteger(0); private AtomicInteger mIdCounter = new AtomicInteger(0);
private ResizableExpandableFloatyWindow mFloatyWindow; private ResizableExpandableFloatyWindow mFloatyWindow;
private ConsoleFloaty mConsoleFloaty; private ConsoleFloaty mConsoleFloaty;
private LogListener mLogListener; private WeakReference<LogListener> mLogListener;
private UiHandler mUiHandler; private UiHandler mUiHandler;
private BlockingQueue<String> mInput = new ArrayBlockingQueue<>(1); private BlockingQueue<String> mInput = new ArrayBlockingQueue<>(1);
private WeakReference<ConsoleView> mConsoleView; private WeakReference<ConsoleView> mConsoleView;
@@ -96,8 +96,9 @@ public class StardustConsole extends AbstractConsole {
} }
} }
public void setLogListener(LogListener logListener) { public void setLogListener(LogListener logListener) {
mLogListener = logListener; mLogListener = new WeakReference<>(logListener);
} }
public ArrayList<Log> getAllLogs() { public ArrayList<Log> getAllLogs() {
@@ -111,8 +112,8 @@ public class StardustConsole extends AbstractConsole {
if (mGlobalConsole != null) { if (mGlobalConsole != null) {
mGlobalConsole.println(level, charSequence); mGlobalConsole.println(level, charSequence);
} }
if (mLogListener != null) { if (mLogListener != null && mLogListener.get() != null) {
mLogListener.onNewLog(log); mLogListener.get().onNewLog(log);
} }
} }
@@ -124,8 +125,8 @@ public class StardustConsole extends AbstractConsole {
if (mGlobalConsole != null) { if (mGlobalConsole != null) {
mGlobalConsole.print(level, charSequence); mGlobalConsole.print(level, charSequence);
} }
if (mLogListener != null) { if (mLogListener != null && mLogListener.get() != null) {
mLogListener.onNewLog(log); mLogListener.get().onNewLog(log);
} }
} }
@@ -133,8 +134,8 @@ public class StardustConsole extends AbstractConsole {
@Override @Override
public void clear() { public void clear() {
mLogs.clear(); mLogs.clear();
if (mLogListener != null) { if (mLogListener != null && mLogListener.get() != null) {
mLogListener.onLogClear(); mLogListener.get().onLogClear();
} }
} }

View File

@@ -1,5 +1,12 @@
package com.stardust.autojs.core.ui.xml; package com.stardust.autojs.core.ui.xml;
import com.stardust.autojs.core.ui.widget.JsButton;
import com.stardust.autojs.core.ui.widget.JsEditText;
import com.stardust.autojs.core.ui.widget.JsFrameLayout;
import com.stardust.autojs.core.ui.widget.JsLinearLayout;
import com.stardust.autojs.core.ui.widget.JsRelativeLayout;
import com.stardust.autojs.core.ui.widget.JsTextView;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap; import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node; import org.w3c.dom.Node;
@@ -21,14 +28,14 @@ import javax.xml.parsers.ParserConfigurationException;
public class XmlConverter { public class XmlConverter {
private static final NodeHandler NODE_HANDLER = new NodeHandler.NameRouter() private static final NodeHandler NODE_HANDLER = new NodeHandler.NameRouter()
.handler("vertical", new NodeHandler.VerticalHandler("com.stardust.autojs.runtime.api.ui.widget.JsLinearLayout")) .handler("vertical", new NodeHandler.VerticalHandler(JsLinearLayout.class.getName()))
.defaultHandler(new NodeHandler.MapNameHandler() .defaultHandler(new NodeHandler.MapNameHandler()
.map("frame", "com.stardust.autojs.runtime.api.ui.widget.JsFrameLayout") .map("frame", JsFrameLayout.class.getName())
.map("linear", "com.stardust.autojs.runtime.api.ui.widget.JsLinearLayout") .map("linear", JsLinearLayout.class.getName())
.map("relative", "com.stardust.autojs.runtime.api.ui.widget.JsRelativeLayout") .map("relative", JsRelativeLayout.class.getName())
.map("button", "com.stardust.autojs.runtime.api.ui.widget.JsButton") .map("button", JsButton.class.getName())
.map("text", "com.stardust.autojs.runtime.api.ui.widget.JsTextView") .map("text", JsTextView.class.getName())
.map("input", "com.stardust.autojs.runtime.api.ui.widget.JsEditText") .map("input", JsEditText.class.getName())
.map("image", "ImageView") .map("image", "ImageView")
); );

View File

@@ -44,9 +44,7 @@ public class LoopedBasedJavaScriptExecution extends RunnableScriptExecution {
return true; return true;
} }
}); });
javaScriptEngine.execute( javaScriptEngine.execute(getSource());
getSource());
return null; return null;
} }

View File

@@ -39,7 +39,7 @@ public class ScriptExecuteActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
IntentExtras extras = IntentExtras.fromIntent(getIntent()); IntentExtras extras = IntentExtras.fromIntent(getIntent());
if (extras == null || extras.get(EXTRA_EXECUTION) == null) { if (extras.get(EXTRA_EXECUTION) == null) {
finish(); finish();
return; return;
} }

View File

@@ -27,6 +27,7 @@ import com.stardust.autojs.runtime.exception.ScriptInterruptedException;
import com.stardust.autojs.core.accessibility.SimpleActionAutomator; import com.stardust.autojs.core.accessibility.SimpleActionAutomator;
import com.stardust.concurrent.VolatileBox; import com.stardust.concurrent.VolatileBox;
import com.stardust.autojs.runtime.api.UI; import com.stardust.autojs.runtime.api.UI;
import com.stardust.concurrent.VolatileDispose;
import com.stardust.pio.UncheckedIOException; import com.stardust.pio.UncheckedIOException;
import com.stardust.util.ClipboardUtil; import com.stardust.util.ClipboardUtil;
import com.stardust.autojs.core.util.ProcessShell; import com.stardust.autojs.core.util.ProcessShell;
@@ -237,7 +238,7 @@ public class ScriptRuntime {
if (Looper.myLooper() == Looper.getMainLooper()) { if (Looper.myLooper() == Looper.getMainLooper()) {
return ClipboardUtil.getClipOrEmpty(mUiHandler.getContext()).toString(); return ClipboardUtil.getClipOrEmpty(mUiHandler.getContext()).toString();
} }
final VolatileBox<String> clip = new VolatileBox<>(""); final VolatileDispose<String> clip = new VolatileDispose<>();
mUiHandler.post(new Runnable() { mUiHandler.post(new Runnable() {
@Override @Override
public void run() { public void run() {

View File

@@ -25,6 +25,7 @@ repositories {
flatDir { flatDir {
dirs 'libs' dirs 'libs'
} }
google()
} }
dependencies { dependencies {
@@ -32,6 +33,6 @@ dependencies {
exclude group: 'com.android.support', module: 'support-annotations' exclude group: 'com.android.support', module: 'support-annotations'
}) })
testCompile 'junit:junit:4.12' testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:25.3.1' compile 'com.android.support:appcompat-v7:25.4.0'
compile project(path: ':common') compile project(path: ':common')
} }

View File

@@ -11,6 +11,7 @@ import android.support.annotation.RequiresApi;
import android.view.ViewConfiguration; import android.view.ViewConfiguration;
import com.stardust.concurrent.VolatileBox; import com.stardust.concurrent.VolatileBox;
import com.stardust.concurrent.VolatileDispose;
import com.stardust.util.ScreenMetrics; import com.stardust.util.ScreenMetrics;
/** /**
@@ -110,7 +111,7 @@ public class GlobalActionAutomator {
@RequiresApi(api = Build.VERSION_CODES.N) @RequiresApi(api = Build.VERSION_CODES.N)
private boolean gesturesWithHandler(GestureDescription description) { private boolean gesturesWithHandler(GestureDescription description) {
final VolatileBox<Boolean> result = new VolatileBox<>(false); final VolatileDispose<Boolean> result = new VolatileDispose<>();
mService.dispatchGesture(description, new AccessibilityService.GestureResultCallback() { mService.dispatchGesture(description, new AccessibilityService.GestureResultCallback() {
@Override @Override
public void onCompleted(GestureDescription gestureDescription) { public void onCompleted(GestureDescription gestureDescription) {

View File

@@ -0,0 +1,52 @@
package com.stardust.concurrent;
/**
* Created by Stardust on 2017/10/28.
*/
public class VolatileDispose<T> {
private volatile T mValue;
public T blockedGet() {
synchronized (this) {
if (mValue != null) {
return mValue;
}
try {
this.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
return mValue;
}
public T blockedGetOrThrow(Class<? extends RuntimeException> exception) {
synchronized (this) {
if (mValue != null) {
return mValue;
}
try {
this.wait();
} catch (InterruptedException e) {
try {
throw exception.newInstance();
} catch (InstantiationException e1) {
throw new RuntimeException(e1);
} catch (IllegalAccessException e1) {
throw new RuntimeException(e1);
}
}
}
return mValue;
}
public void setAndNotify(T value) {
synchronized (this) {
mValue = value;
notify();
}
}
}

View File

@@ -36,6 +36,7 @@ repositories {
flatDir { flatDir {
dirs 'libs' dirs 'libs'
} }
google()
} }
dependencies { dependencies {
@@ -43,7 +44,7 @@ dependencies {
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations' exclude group: 'com.android.support', module: 'support-annotations'
}) })
compile 'com.android.support:appcompat-v7:25.3.1' compile 'com.android.support:appcompat-v7:25.4.0'
testCompile 'junit:junit:4.12' testCompile 'junit:junit:4.12'
compile project(':automator') compile project(':automator')
compile project(':common') compile project(':common')