Add: Task manager

This commit is contained in:
hyb1996
2017-04-04 00:26:14 +08:00
parent 59811a4a5d
commit b762ceb60b
54 changed files with 758 additions and 329 deletions

View File

@@ -2,6 +2,37 @@
<profile version="1.0"> <profile version="1.0">
<option name="myName" value="Project Default" /> <option name="myName" value="Project Default" />
<inspection_tool class="AndroidLintContentDescription" enabled="false" level="WARNING" enabled_by_default="false" /> <inspection_tool class="AndroidLintContentDescription" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="JavaDoc" enabled="true" level="WARNING" enabled_by_default="true">
<option name="TOP_LEVEL_CLASS_OPTIONS">
<value>
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
<option name="REQUIRED_TAGS" value="" />
</value>
</option>
<option name="INNER_CLASS_OPTIONS">
<value>
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
<option name="REQUIRED_TAGS" value="" />
</value>
</option>
<option name="METHOD_OPTIONS">
<value>
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
<option name="REQUIRED_TAGS" value="@return@param@throws or @exception" />
</value>
</option>
<option name="FIELD_OPTIONS">
<value>
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
<option name="REQUIRED_TAGS" value="" />
</value>
</option>
<option name="IGNORE_DEPRECATED" value="false" />
<option name="IGNORE_JAVADOC_PERIOD" value="true" />
<option name="IGNORE_DUPLICATED_THROWS" value="false" />
<option name="IGNORE_POINT_TO_ITSELF" value="false" />
<option name="myAdditionalJavadocTags" value="hide" />
</inspection_tool>
<inspection_tool class="LoggerInitializedWithForeignClass" enabled="false" level="WARNING" enabled_by_default="false"> <inspection_tool class="LoggerInitializedWithForeignClass" enabled="false" level="WARNING" enabled_by_default="false">
<option name="loggerClassName" value="org.apache.log4j.Logger,org.slf4j.LoggerFactory,org.apache.commons.logging.LogFactory,java.util.logging.Logger" /> <option name="loggerClassName" value="org.apache.log4j.Logger,org.slf4j.LoggerFactory,org.apache.commons.logging.LogFactory,java.util.logging.Logger" />
<option name="loggerFactoryMethodName" value="getLogger,getLogger,getLog,getLogger" /> <option name="loggerFactoryMethodName" value="getLogger,getLogger,getLog,getLogger" />

View File

@@ -8,8 +8,8 @@ android {
applicationId "com.stardust.scriptdroid" applicationId "com.stardust.scriptdroid"
minSdkVersion 19 minSdkVersion 19
targetSdkVersion 23 targetSdkVersion 23
versionCode 113 versionCode 114
versionName "2.0.6 Alpha3" versionName "2.0.7 Alpha"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
multiDexEnabled true multiDexEnabled true
@@ -71,7 +71,6 @@ dependencies {
compile 'org.greenrobot:eventbus:3.0.0' compile 'org.greenrobot:eventbus:3.0.0'
compile 'com.bignerdranch.android:expandablerecyclerview:3.0.0-RC1' compile 'com.bignerdranch.android:expandablerecyclerview:3.0.0-RC1'
compile 'com.ashokvarma.android:bottom-navigation-bar:1.4.1' compile 'com.ashokvarma.android:bottom-navigation-bar:1.4.1'
compile 'com.github.hyb1996:node-android-lib:1.0.13'
compile 'com.yqritc:recyclerview-flexibledivider:1.4.0' compile 'com.yqritc:recyclerview-flexibledivider:1.4.0'
compile 'me.zhanghai.android.materialprogressbar:library:1.3.0' compile 'me.zhanghai.android.materialprogressbar:library:1.3.0'
compile group:'com.twofortyfouram', name:'android-plugin-client-sdk-for-locale', version:'[4.0.2, 5.0[' compile group:'com.twofortyfouram', name:'android-plugin-client-sdk-for-locale', version:'[4.0.2, 5.0['

View File

@@ -11,6 +11,7 @@ import android.view.ViewGroup;
import android.view.WindowManager; import android.view.WindowManager;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import android.workground.WrapContentLinearLayoutManager;
import com.afollestad.materialdialogs.MaterialDialog; import com.afollestad.materialdialogs.MaterialDialog;
import com.stardust.scriptdroid.scripts.ScriptFile; import com.stardust.scriptdroid.scripts.ScriptFile;
@@ -74,7 +75,7 @@ public class FloatingScriptFileListView extends RecyclerView {
private void init() { private void init() {
setAdapter(new Adapter()); setAdapter(new Adapter());
setLayoutManager(new LinearLayoutManager(getContext())); setLayoutManager(new WrapContentLinearLayoutManager(getContext()));
addItemDecoration(new DividerItemDecoration(getContext(), DividerItemDecoration.VERTICAL)); addItemDecoration(new DividerItemDecoration(getContext(), DividerItemDecoration.VERTICAL));
initScriptFileOperationPopupMenu(); initScriptFileOperationPopupMenu();
} }

View File

@@ -67,7 +67,7 @@ public class StorageScriptProvider {
public void notifyDirectoryChanged(ScriptFile directory) { public void notifyDirectoryChanged(ScriptFile directory) {
if (directory.equals(mInitialDirectory)) { if (directory.equals(mInitialDirectory)) {
mInitialDirectoryScriptFiles = getInitialDirectoryScriptFiles(); mInitialDirectoryScriptFiles = getInitialDirectoryScriptFilesInner();
} else { } else {
clearCache(directory); clearCache(directory);
} }
@@ -80,6 +80,7 @@ public class StorageScriptProvider {
mDirectoryEventBus.post(new DirectoryChangeEvent(mInitialDirectory)); mDirectoryEventBus.post(new DirectoryChangeEvent(mInitialDirectory));
} }
@SuppressWarnings("unchecked")
public void refreshAll() { public void refreshAll() {
Map<String, ScriptFile> files = (Map<String, ScriptFile>) mScriptFileCache.clone(); Map<String, ScriptFile> files = (Map<String, ScriptFile>) mScriptFileCache.clone();
mScriptFileCache.clear(); mScriptFileCache.clear();

View File

@@ -16,12 +16,13 @@ import android.view.View;
import com.afollestad.materialdialogs.DialogAction; import com.afollestad.materialdialogs.DialogAction;
import com.afollestad.materialdialogs.MaterialDialog; import com.afollestad.materialdialogs.MaterialDialog;
import com.stardust.autojs.engine.JavaScriptEngine; import com.stardust.autojs.engine.JavaScriptEngine;
import com.stardust.autojs.engine.ScriptExecutionListener; import com.stardust.autojs.ScriptExecutionListener;
import com.stardust.autojs.script.FileScriptSource; import com.stardust.autojs.script.FileScriptSource;
import com.stardust.autojs.script.ScriptSource; import com.stardust.autojs.script.ScriptSource;
import com.stardust.pio.PFile; import com.stardust.pio.PFile;
import com.stardust.scriptdroid.Pref; import com.stardust.scriptdroid.Pref;
import com.stardust.scriptdroid.autojs.AutoJs; import com.stardust.scriptdroid.autojs.AutoJs;
import com.stardust.scriptdroid.scripts.ScriptFile;
import com.stardust.scriptdroid.ui.edit.editor920.Editor920Activity; import com.stardust.scriptdroid.ui.edit.editor920.Editor920Activity;
import com.stardust.scriptdroid.ui.edit.sidemenu.EditSideMenuFragment; import com.stardust.scriptdroid.ui.edit.sidemenu.EditSideMenuFragment;
import com.stardust.scriptdroid.ui.edit.sidemenu.FunctionListRecyclerView; import com.stardust.scriptdroid.ui.edit.sidemenu.FunctionListRecyclerView;
@@ -42,8 +43,6 @@ import com.stardust.theme.ThemeColorManager;
import com.stardust.view.ViewBinder; import com.stardust.view.ViewBinder;
import java.io.File; import java.io.File;
import java.text.DateFormat;
import java.util.Date;
import timber.log.Timber; import timber.log.Timber;
@@ -99,6 +98,10 @@ public class EditActivity extends Editor920Activity {
.putExtra("name", name)); .putExtra("name", name));
} }
public static void editFile(Context context, ScriptFile file) {
editFile(context, file.getSimplifiedName(), file.getPath());
}
private String mName; private String mName;
private File mFile; private File mFile;
private View mView; private View mView;
@@ -264,7 +267,7 @@ public class EditActivity extends Editor920Activity {
private void run() { private void run() {
Snackbar.make(mView, R.string.text_start_running, Snackbar.LENGTH_SHORT).show(); Snackbar.make(mView, R.string.text_start_running, Snackbar.LENGTH_SHORT).show();
setMenuStatus(R.id.run, MenuDef.STATUS_DISABLED); setMenuStatus(R.id.run, MenuDef.STATUS_DISABLED);
AutoJs.getInstance().getScriptEngineService().execute(new FileScriptSource(mFile), SCRIPT_EXECUTION_LISTENER); AutoJs.getInstance().getScriptEngineService().execute(new FileScriptSource(mName, mFile), SCRIPT_EXECUTION_LISTENER);
} }
@ViewBinding.Click(R.id.undo) @ViewBinding.Click(R.id.undo)

View File

@@ -12,6 +12,7 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import android.workground.WrapContentLinearLayoutManager;
import com.stardust.scriptdroid.App; import com.stardust.scriptdroid.App;
import com.stardust.scriptdroid.R; import com.stardust.scriptdroid.R;
@@ -77,8 +78,8 @@ public class InputMethodEnhanceBar extends RecyclerView implements CodeCompletio
private void init() { private void init() {
setAdapter(new CodeCompletionAdapter()); setAdapter(new CodeCompletionAdapter());
setLayoutManager(new LinearLayoutManager(getContext(), HORIZONTAL, false)); setLayoutManager(new WrapContentLinearLayoutManager(getContext(), HORIZONTAL, false));
mCodeCompletion.setFunctions(AutoJs.getInstance().getScriptEngineService().getJavaScriptEngineManager().getGlobalFunctions()); mCodeCompletion.setFunctions(AutoJs.getInstance().getScriptEngineService().getGlobalFunctions());
} }
public void setEditTextBridge(EditTextBridge editTextBridge) { public void setEditTextBridge(EditTextBridge editTextBridge) {

View File

@@ -11,6 +11,7 @@ import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.TextView; import android.widget.TextView;
import android.workground.WrapContentLinearLayoutManager;
import com.stardust.pio.PFile; import com.stardust.pio.PFile;
import com.stardust.scriptdroid.App; import com.stardust.scriptdroid.App;
@@ -118,7 +119,7 @@ public class HelpCatalogueActivity extends BaseActivity {
private void setUpRecyclerView() { private void setUpRecyclerView() {
mRecyclerView = $(R.id.catalogue); mRecyclerView = $(R.id.catalogue);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); mRecyclerView.setLayoutManager(new WrapContentLinearLayoutManager(this));
mRecyclerView.setAdapter(new Adapter()); mRecyclerView.setAdapter(new Adapter());
mRecyclerView.addItemDecoration(new DividerItemDecoration(this, RecyclerView.VERTICAL)); mRecyclerView.addItemDecoration(new DividerItemDecoration(this, RecyclerView.VERTICAL));
} }

View File

@@ -16,6 +16,7 @@ import android.view.WindowManager;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.PopupWindow; import android.widget.PopupWindow;
import android.widget.TextView; import android.widget.TextView;
import android.workground.WrapContentLinearLayoutManager;
import com.stardust.util.ViewUtil; import com.stardust.util.ViewUtil;
import com.stardust.scriptdroid.R; import com.stardust.scriptdroid.R;
@@ -130,7 +131,7 @@ public class ScriptFileOperationPopupMenu extends PopupWindow {
} }
private void init() { private void init() {
setLayoutManager(new LinearLayoutManager(getContext())); setLayoutManager(new WrapContentLinearLayoutManager(getContext()));
setAdapter(new Adapter<ViewHolder>() { setAdapter(new Adapter<ViewHolder>() {
@Override @Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

View File

@@ -10,6 +10,7 @@ import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.TextView; import android.widget.TextView;
import android.workground.WrapContentLinearLayoutManager;
import com.bignerdranch.expandablerecyclerview.ChildViewHolder; import com.bignerdranch.expandablerecyclerview.ChildViewHolder;
import com.bignerdranch.expandablerecyclerview.ExpandableRecyclerAdapter; import com.bignerdranch.expandablerecyclerview.ExpandableRecyclerAdapter;
@@ -96,7 +97,7 @@ public class SampleScriptListRecyclerView extends RecyclerView {
} }
private void init() { private void init() {
setLayoutManager(new LinearLayoutManager(getContext())); setLayoutManager(new WrapContentLinearLayoutManager(getContext()));
addItemDecoration(new DividerItemDecoration(getContext(), VERTICAL)); addItemDecoration(new DividerItemDecoration(getContext(), VERTICAL));
} }

View File

@@ -17,6 +17,7 @@ import com.stardust.scriptdroid.scripts.ScriptFile;
import com.stardust.pio.PFile; import com.stardust.pio.PFile;
import com.stardust.scriptdroid.R; import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.scripts.StorageScriptProvider; import com.stardust.scriptdroid.scripts.StorageScriptProvider;
import com.stardust.scriptdroid.ui.edit.EditActivity;
import com.stardust.scriptdroid.ui.main.operation.ScriptFileOperation; import com.stardust.scriptdroid.ui.main.operation.ScriptFileOperation;
import com.stardust.theme.dialog.ThemeColorMaterialDialogBuilder; import com.stardust.theme.dialog.ThemeColorMaterialDialogBuilder;
import com.stardust.view.ViewBinder; import com.stardust.view.ViewBinder;
@@ -82,8 +83,7 @@ public class MyScriptListFragment extends Fragment {
mScriptListRecyclerView.setOnItemClickListener(new ScriptAndFolderListRecyclerView.OnScriptFileClickListener() { mScriptListRecyclerView.setOnItemClickListener(new ScriptAndFolderListRecyclerView.OnScriptFileClickListener() {
@Override @Override
public void onClick(ScriptFile file) { public void onClick(ScriptFile file) {
mSelectedScriptFile = file; EditActivity.editFile(getContext(), file);
mScriptFileOperationDialog.show();
} }
}); });
mScriptListRecyclerView.setOnItemLongClickListener(new ScriptAndFolderListRecyclerView.OnScriptFileLongClickListener() { mScriptListRecyclerView.setOnItemLongClickListener(new ScriptAndFolderListRecyclerView.OnScriptFileLongClickListener() {

View File

@@ -4,7 +4,6 @@ import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import android.os.Parcelable; import android.os.Parcelable;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet; import android.util.AttributeSet;
@@ -12,14 +11,16 @@ import android.view.KeyEvent;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.RelativeLayout;
import android.widget.TextView; import android.widget.TextView;
import android.workground.WrapContentLinearLayoutManager;
import com.stardust.autojs.script.FileScriptSource; import com.stardust.autojs.script.FileScriptSource;
import com.stardust.scriptdroid.autojs.AutoJs; import com.stardust.scriptdroid.autojs.AutoJs;
import com.stardust.scriptdroid.scripts.ScriptFile; import com.stardust.scriptdroid.scripts.ScriptFile;
import com.stardust.scriptdroid.R; import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.scripts.StorageScriptProvider; import com.stardust.scriptdroid.scripts.StorageScriptProvider;
import com.stardust.scriptdroid.ui.main.operation.ScriptFileOperation; import com.yqritc.recyclerviewflexibledivider.HorizontalDividerItemDecoration;
import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.Subscribe;
@@ -58,7 +59,7 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView {
} }
ScriptFile file = mScriptFileList[getActualPosition(position)]; ScriptFile file = mScriptFileList[getActualPosition(position)];
if (file.isDirectory()) { if (file.isDirectory()) {
setCurrentFolder(file, true); setCurrentDirectory(file, true);
} else if (mOnItemClickListener != null) { } else if (mOnItemClickListener != null) {
mOnItemClickListener.onClick(file); mOnItemClickListener.onClick(file);
} }
@@ -84,17 +85,10 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView {
AutoJs.getInstance().getScriptEngineService().execute(new FileScriptSource(file)); AutoJs.getInstance().getScriptEngineService().execute(new FileScriptSource(file));
} }
}; };
private OnClickListener mOnEditClickListener = new OnClickListener() {
@Override
public void onClick(View v) {
int position = getChildViewHolder((View) v.getParent()).getAdapterPosition();
ScriptFileOperation.edit(mScriptFileList[getActualPosition(position)]);
}
};
private ScriptFile[] mScriptFileList = new ScriptFile[0]; private ScriptFile[] mScriptFileList = new ScriptFile[0];
private ScriptFile mCurrentFolder; private ScriptFile mCurrentDirectory;
private ScriptFile mRootFolder; private ScriptFile mRootDirectory;
private Adapter mAdapter; private Adapter mAdapter;
private boolean mCanGoBack = false; private boolean mCanGoBack = false;
private StorageScriptProvider mStorageScriptProvider; private StorageScriptProvider mStorageScriptProvider;
@@ -116,8 +110,8 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView {
init(); init();
} }
private void setCurrentFolder(final ScriptFile folder, boolean canGoBack) { private void setCurrentDirectory(final ScriptFile folder, boolean canGoBack) {
mCurrentFolder = folder; mCurrentDirectory = folder;
mCanGoBack = canGoBack; mCanGoBack = canGoBack;
if (mFileProcessListener != null) { if (mFileProcessListener != null) {
mFileProcessListener.onFilesListing(); mFileProcessListener.onFilesListing();
@@ -137,9 +131,9 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView {
}).start(); }).start();
} }
private void setRootFolder(ScriptFile folder) { private void setRootDirectory(ScriptFile folder) {
mRootFolder = folder; mRootDirectory = folder;
setCurrentFolder(mRootFolder, false); setCurrentDirectory(mRootDirectory, false);
} }
public void setFileProcessListener(FileProcessListener fileProcessListener) { public void setFileProcessListener(FileProcessListener fileProcessListener) {
@@ -151,7 +145,7 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView {
mStorageScriptProvider.unregisterDirectoryChangeListener(this); mStorageScriptProvider.unregisterDirectoryChangeListener(this);
mStorageScriptProvider = storageScriptProvider; mStorageScriptProvider = storageScriptProvider;
mStorageScriptProvider.registerDirectoryChangeListener(this); mStorageScriptProvider.registerDirectoryChangeListener(this);
setRootFolder(mStorageScriptProvider.getInitialDirectory()); setRootDirectory(mStorageScriptProvider.getInitialDirectory());
} }
public void setOnItemClickListener(OnScriptFileClickListener onItemClickListener) { public void setOnItemClickListener(OnScriptFileClickListener onItemClickListener) {
@@ -163,7 +157,7 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView {
} }
public ScriptFile getCurrentDirectory() { public ScriptFile getCurrentDirectory() {
return mCurrentFolder; return mCurrentDirectory;
} }
public void setScriptFileOperationEnabled(boolean scriptFileOperationEnabled) { public void setScriptFileOperationEnabled(boolean scriptFileOperationEnabled) {
@@ -171,13 +165,18 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView {
} }
private void goBack() { private void goBack() {
ScriptFile parent = mCurrentFolder.getParentFile(); ScriptFile parent = mCurrentDirectory.getParentFile();
setCurrentFolder(parent, !parent.equals(mRootFolder)); setCurrentDirectory(parent, !parent.equals(mRootDirectory));
} }
private void init() { private void init() {
setLayoutManager(new LinearLayoutManager(getContext())); setLayoutManager(new WrapContentLinearLayoutManager(getContext()));
addItemDecoration(new DividerItemDecoration(getContext(), VERTICAL)); addItemDecoration(new HorizontalDividerItemDecoration.Builder(getContext())
.color(0xffd9d9d9)
.size(2)
.marginResId(R.dimen.script_and_folder_list_divider_left_margin, R.dimen.script_and_folder_list_divider_right_margin)
.showLastDivider()
.build());
mAdapter = new Adapter(); mAdapter = new Adapter();
setAdapter(mAdapter); setAdapter(mAdapter);
} }
@@ -186,17 +185,17 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView {
protected Parcelable onSaveInstanceState() { protected Parcelable onSaveInstanceState() {
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putParcelable("superData", super.onSaveInstanceState()); bundle.putParcelable("superData", super.onSaveInstanceState());
bundle.putSerializable("current", mCurrentFolder); bundle.putSerializable("current", mCurrentDirectory);
bundle.putSerializable("root", mRootFolder); bundle.putSerializable("root", mRootDirectory);
return bundle; return bundle;
} }
@Override @Override
protected void onRestoreInstanceState(Parcelable state) { protected void onRestoreInstanceState(Parcelable state) {
Bundle bundle = (Bundle) state; Bundle bundle = (Bundle) state;
mRootFolder = (ScriptFile) bundle.getSerializable("root"); mRootDirectory = (ScriptFile) bundle.getSerializable("root");
mCurrentFolder = (ScriptFile) bundle.getSerializable("current"); mCurrentDirectory = (ScriptFile) bundle.getSerializable("current");
setCurrentFolder(mCurrentFolder, !mCurrentFolder.equals(mRootFolder)); setCurrentDirectory(mCurrentDirectory, !mCurrentDirectory.equals(mRootDirectory));
super.onRestoreInstanceState(bundle.getParcelable("superData")); super.onRestoreInstanceState(bundle.getParcelable("superData"));
} }
@@ -226,13 +225,13 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView {
@Subscribe @Subscribe
public void onDirectoryChange(StorageScriptProvider.DirectoryChangeEvent event) { public void onDirectoryChange(StorageScriptProvider.DirectoryChangeEvent event) {
if (event.directory.equals(mCurrentFolder)) { if (event.directory.equals(mCurrentDirectory)) {
updateCurrentFolder(); updateCurrentDirectory();
} }
} }
private void updateCurrentFolder() { private void updateCurrentDirectory() {
setCurrentFolder(mCurrentFolder, mCanGoBack); setCurrentDirectory(mCurrentDirectory, mCanGoBack);
} }
private class Adapter extends RecyclerView.Adapter<ViewHolder> { private class Adapter extends RecyclerView.Adapter<ViewHolder> {
@@ -244,9 +243,9 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView {
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) { switch (viewType) {
case VIEW_TYPE_FILE: case VIEW_TYPE_FILE:
return new FileViewHolder(LayoutInflater.from(getContext()).inflate(R.layout.script_list_recycler_view_item, parent, false)); return new FileViewHolder(LayoutInflater.from(getContext()).inflate(R.layout.script_and_folder_list_recycler_view_file, parent, false));
case VIEW_TYPE_FOLDER: case VIEW_TYPE_FOLDER:
return new ViewHolder(LayoutInflater.from(getContext()).inflate(R.layout.script_list_recycler_view_folder, parent, false)); return new ViewHolder(LayoutInflater.from(getContext()).inflate(R.layout.script_and_folder_list_recycler_view_directory, parent, false));
} }
return null; return null;
} }
@@ -255,7 +254,6 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView {
public void onBindViewHolder(ViewHolder holder, int position) { public void onBindViewHolder(ViewHolder holder, int position) {
if (mCanGoBack && position == 0) { if (mCanGoBack && position == 0) {
holder.name.setText(".."); holder.name.setText("..");
holder.path.setText("");
} else } else
holder.bind(mScriptFileList[getActualPosition(position)]); holder.bind(mScriptFileList[getActualPosition(position)]);
} }
@@ -281,19 +279,30 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView {
private class ViewHolder extends RecyclerView.ViewHolder { private class ViewHolder extends RecyclerView.ViewHolder {
TextView name, path; TextView name;
ViewHolder(View itemView) { ViewHolder(View itemView) {
super(itemView); super(itemView);
itemView.setOnClickListener(mOnItemClickListenerProxy); itemView.setOnClickListener(mOnItemClickListenerProxy);
itemView.setOnLongClickListener(mOnItemLongClickListenerProxy); itemView.setOnLongClickListener(mOnItemLongClickListenerProxy);
name = (TextView) itemView.findViewById(R.id.name); name = (TextView) itemView.findViewById(R.id.name);
path = (TextView) itemView.findViewById(R.id.path); if (!mScriptFileOperationEnabled) {
setMarginRight(name, 0);
}
}
private void setMarginRight(View view, int marginRight) {
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view.getLayoutParams();
layoutParams.rightMargin = marginRight;
view.setLayoutParams(layoutParams);
} }
public void bind(ScriptFile file) { public void bind(ScriptFile file) {
name.setText(file.getSimplifiedName()); if (file.isDirectory()) {
path.setText(file.getSimplifiedPath()); name.setText(file.getName());
} else {
name.setText(file.getSimplifiedName());
}
} }
} }
@@ -302,10 +311,8 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView {
FileViewHolder(View itemView) { FileViewHolder(View itemView) {
super(itemView); super(itemView);
if (mScriptFileOperationEnabled) { if (mScriptFileOperationEnabled) {
itemView.findViewById(R.id.edit).setOnClickListener(mOnEditClickListener);
itemView.findViewById(R.id.run).setOnClickListener(mOnRunClickListener); itemView.findViewById(R.id.run).setOnClickListener(mOnRunClickListener);
} else { } else {
itemView.findViewById(R.id.edit).setVisibility(GONE);
itemView.findViewById(R.id.run).setVisibility(GONE); itemView.findViewById(R.id.run).setVisibility(GONE);
} }
} }

View File

@@ -12,6 +12,7 @@ import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.TextView; import android.widget.TextView;
import android.workground.WrapContentLinearLayoutManager;
import com.stardust.scriptdroid.scripts.ScriptFile; import com.stardust.scriptdroid.scripts.ScriptFile;
import com.stardust.scriptdroid.scripts.ScriptFileList; import com.stardust.scriptdroid.scripts.ScriptFileList;
@@ -87,7 +88,7 @@ public class ScriptListRecyclerView extends ThemeColorRecyclerView {
private void init() { private void init() {
setAdapter(new Adapter()); setAdapter(new Adapter());
setLayoutManager(new LinearLayoutManager(getContext())); setLayoutManager(new WrapContentLinearLayoutManager(getContext()));
addItemDecoration(new DividerItemDecoration(getContext(), DividerItemDecoration.VERTICAL)); addItemDecoration(new DividerItemDecoration(getContext(), DividerItemDecoration.VERTICAL));
} }

View File

@@ -0,0 +1,161 @@
package com.stardust.scriptdroid.ui.main.task;
import android.content.Context;
import android.support.annotation.Nullable;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.ThemeColorRecyclerView;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.workground.WrapContentLinearLayoutManager;
import com.stardust.autojs.ScriptEngineService;
import com.stardust.autojs.engine.JavaScriptEngine;
import com.stardust.autojs.engine.JavaScriptEngineManager;
import com.stardust.autojs.script.ScriptSource;
import com.stardust.scriptdroid.R;
import com.yqritc.recyclerviewflexibledivider.HorizontalDividerItemDecoration;
import java.util.LinkedList;
import java.util.List;
/**
* Created by Stardust on 2017/3/24.
*/
public class TaskListRecyclerView extends ThemeColorRecyclerView implements JavaScriptEngineManager.EngineLifecycleCallback {
private final OnClickListener mOnItemClickListenerProxy = new OnClickListener() {
@Override
public void onClick(View v) {
}
};
private final OnClickListener mOnStopClickListener = new OnClickListener() {
@Override
public void onClick(View v) {
int position = getChildViewHolder((View) v.getParent()).getAdapterPosition();
mScriptEngines.get(position).forceStop();
}
};
private final List<JavaScriptEngine> mScriptEngines = new LinkedList<>();
private Adapter mAdapter;
public TaskListRecyclerView(Context context) {
super(context);
init();
}
public TaskListRecyclerView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public TaskListRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
setLayoutManager(new WrapContentLinearLayoutManager(getContext()));
addItemDecoration(new HorizontalDividerItemDecoration.Builder(getContext())
.color(0xffd9d9d9)
.size(2)
.marginResId(R.dimen.script_and_folder_list_divider_left_margin, R.dimen.script_and_folder_list_divider_right_margin)
.showLastDivider()
.build());
mAdapter = new Adapter();
setAdapter(mAdapter);
}
private void updateEngineList() {
mScriptEngines.clear();
mScriptEngines.addAll(ScriptEngineService.getInstance().getEngines());
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
updateEngineList();
mAdapter.notifyDataSetChanged();
ScriptEngineService.getInstance().registerEngineLifecycleCallback(this);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
ScriptEngineService.getInstance().unregisterEngineLifecycleCallback(this);
}
@Override
public void onEngineCreate(final JavaScriptEngine engine) {
synchronized (mScriptEngines) {
post(new Runnable() {
@Override
public void run() {
mScriptEngines.add(engine);
getAdapter().notifyItemInserted(mScriptEngines.size() - 1);
}
});
}
}
@Override
public void onEngineRemove(final JavaScriptEngine engine) {
post(new Runnable() {
@Override
public void run() {
final int i = mScriptEngines.indexOf(engine);
mScriptEngines.remove(i);
mAdapter.notifyItemRemoved(i);
}
});
}
private class Adapter extends RecyclerView.Adapter<ViewHolder> {
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ViewHolder(LayoutInflater.from(getContext()).inflate(R.layout.task_list_recycler_view_item, parent, false));
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.bind(mScriptEngines.get(position).getExecutedScript());
}
@Override
public int getItemCount() {
return mScriptEngines.size();
}
}
private class ViewHolder extends RecyclerView.ViewHolder {
TextView name, detail;
View stop;
ViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(mOnItemClickListenerProxy);
name = (TextView) itemView.findViewById(R.id.name);
detail = (TextView) itemView.findViewById(R.id.detail);
stop = itemView.findViewById(R.id.stop);
stop.setOnClickListener(mOnStopClickListener);
}
public void bind(ScriptSource source) {
if (source == null)
return;
name.setText(source.getName());
detail.setText(source.toString());
}
}
}

View File

@@ -2,20 +2,59 @@ package com.stardust.scriptdroid.ui.main.task;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import com.stardust.app.Fragment; import com.stardust.app.Fragment;
import com.stardust.autojs.ScriptEngineService;
import com.stardust.scriptdroid.R;
import com.stardust.view.ViewBinder;
import com.stardust.view.ViewBinding;
import com.stardust.widget.SimpleAdapterDataObserver;
/** /**
* Created by Stardust on 2017/3/24. * Created by Stardust on 2017/3/24.
*/ */
public class TaskManagerFragment extends Fragment { public class TaskManagerFragment extends Fragment {
private TaskListRecyclerView mTaskListRecyclerView;
private View mCloseAllView;
private View mNoRunningScriptNotice;
@Nullable @Nullable
@Override @Override
public View createView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { public View createView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return null; return inflater.inflate(R.layout.fragment_task_manager, container, false);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ViewBinder.bind(this, view);
init();
}
private void init() {
mNoRunningScriptNotice = $(R.id.notice_no_running_script);
mCloseAllView = $(R.id.close_all);
mTaskListRecyclerView = $(R.id.task_list);
mTaskListRecyclerView.getAdapter().registerAdapterDataObserver(new SimpleAdapterDataObserver() {
@Override
public void onSomethingChanged() {
boolean noRunningScript = mTaskListRecyclerView.getAdapter().getItemCount() == 0;
mNoRunningScriptNotice.setVisibility(noRunningScript ? View.VISIBLE : View.GONE);
mCloseAllView.setVisibility(noRunningScript ? View.GONE : View.VISIBLE);
}
});
}
@ViewBinding.Click(R.id.close_all)
private void closeAllRunningScripts() {
ScriptEngineService.getInstance().stopAll();
} }
} }

View File

@@ -1,8 +0,0 @@
package com.stardust.scriptdroid.ui.main.task;
/**
* Created by Stardust on 2017/3/24.
*/
public class TaskManagerRecyclerView {
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

View File

@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<view
android:id="@+id/console"
class="com.stardust.scriptdroid.ui.console.ConsoleActivity$ConsoleView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>

View File

@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" <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_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"> android:orientation="vertical">

View File

@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#f4f4f4">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="@+id/close_all"
android:layout_width="match_parent"
android:layout_height="42dp"
android:background="#e4e4e4"
android:foreground="?selectableItemBackground"
android:gravity="center_vertical"
android:orientation="horizontal"
android:visibility="gone">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:text="@string/text_close_all_running_scripts"
android:textColor="@android:color/secondary_text_light"
android:textSize="16sp"/>
</LinearLayout>
<com.stardust.scriptdroid.ui.main.task.TaskListRecyclerView
android:id="@+id/task_list"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
<TextView
android:id="@+id/notice_no_running_script"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:text="@string/notice_no_running_script"
android:textColor="#adadad"
android:textSize="16sp"/>
</FrameLayout>

View File

@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:foreground="?android:selectableItemBackground">
<ImageView
android:id="@+id/icon"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_marginBottom="4dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="4dp"
android:contentDescription="@string/_app_name"
android:scaleType="fitCenter"
android:src="@drawable/ic_folder_yellow_100px"/>
<TextView
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="8dp"
android:layout_marginRight="80dp"
android:layout_toRightOf="@id/icon"
android:ellipsize="end"
android:maxLines="1"
android:textColor="@android:color/secondary_text_light"
android:textSize="16sp"
tools:text="示例脚本"/>
</RelativeLayout>

View File

@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:foreground="?android:selectableItemBackground">
<ImageView
android:id="@+id/icon"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_marginBottom="4dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="4dp"
android:contentDescription="@string/_app_name"
android:scaleType="fitCenter"
android:src="@drawable/ic_node_js_black"/>
<TextView
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="8dp"
android:layout_marginRight="80dp"
android:layout_toRightOf="@id/icon"
android:ellipsize="end"
android:maxLines="1"
android:textColor="@android:color/secondary_text_light"
android:textSize="16sp"
tools:text="正在运行的服务"/>
<LinearLayout
android:id="@+id/run"
android:layout_width="42dp"
android:layout_height="42dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="12dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_gravity="center"
android:contentDescription="@string/_app_name"
android:src="@drawable/ic_play"/>
</LinearLayout>
</RelativeLayout>

View File

@@ -1,13 +1,13 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android" <merge xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent"
android:background="#fefefe">
<com.stardust.scriptdroid.ui.main.script_list.ScriptAndFolderListRecyclerView <com.stardust.scriptdroid.ui.main.script_list.ScriptAndFolderListRecyclerView
android:id="@+id/script_list_recycler_view" android:id="@+id/script_list_recycler_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"/>
android:background="#fafafa"/>
<FrameLayout <FrameLayout
android:id="@+id/progressBar" android:id="@+id/progressBar"

View File

@@ -1,53 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:foreground="?android:selectableItemBackground"
android:orientation="vertical"
android:paddingBottom="8dp"
android:paddingLeft="8dp"
android:paddingTop="8dp">
<ImageView
android:id="@+id/icon"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:contentDescription="@string/_app_name"
android:scaleType="fitCenter"
android:src="@drawable/ic_folder_yellow_200px"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_marginLeft="56dp"
android:gravity="center_vertical"
android:orientation="vertical">
<TextView
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:textColor="@android:color/primary_text_light"
android:textSize="18sp"
tools:text="示例脚本"/>
<TextView
android:id="@+id/path"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:ellipsize="end"
android:maxLines="1"
android:gravity="center_vertical"
android:textColor="#777777"
android:textSize="14sp"
tools:text="/storage/emulated/0/脚本/示例脚本"/>
</LinearLayout>
</RelativeLayout>

View File

@@ -0,0 +1,72 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:foreground="?android:selectableItemBackground">
<ImageView
android:id="@+id/icon"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_marginBottom="6dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="6dp"
android:contentDescription="@string/_app_name"
android:scaleType="fitCenter"
android:src="@drawable/ic_node_js_black"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="8dp"
android:layout_marginRight="80dp"
android:layout_toRightOf="@id/icon"
android:orientation="vertical">
<TextView
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:textColor="@android:color/secondary_text_light"
android:textSize="16sp"
tools:text="正在运行的服务"/>
<TextView
android:id="@+id/detail"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:ellipsize="end"
android:maxLines="1"
android:textColor="#777777"
android:textSize="12sp"
tools:text="/storage/emulated/0/脚本/正在运行的服务.txt"/>
</LinearLayout>
<FrameLayout
android:id="@+id/stop"
android:layout_width="42dp"
android:layout_height="42dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="12dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:gravity="center">
<ImageView
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_gravity="center"
android:contentDescription="@string/_app_name"
android:src="@drawable/ic_close"/>
</FrameLayout>
</RelativeLayout>

View File

@@ -157,6 +157,7 @@
<string name="text_off">OFF</string> <string name="text_off">OFF</string>
<string name="text_please_choose_file_to_import">请选择要导入的脚本</string> <string name="text_please_choose_file_to_import">请选择要导入的脚本</string>
<string name="text_refresh">刷新</string> <string name="text_refresh">刷新</string>
<string name="notice_no_running_script"><![CDATA[没有正在运行的脚本 φ(>ω<*)]]></string>
<string-array name="record_control_keys"> <string-array name="record_control_keys">
<item>None</item> <item>None</item>
<item>Volume Up</item> <item>Volume Up</item>

View File

@@ -7,4 +7,6 @@
<dimen name="level_beam_view_line_width">6dp</dimen> <dimen name="level_beam_view_line_width">6dp</dimen>
<dimen name="level_beam_view_line_offset">2dp</dimen> <dimen name="level_beam_view_line_offset">2dp</dimen>
<dimen name="level_beam_view_padding_right">-4dp</dimen> <dimen name="level_beam_view_padding_right">-4dp</dimen>
<dimen name="script_and_folder_list_divider_left_margin">56dp</dimen>
<dimen name="script_and_folder_list_divider_right_margin">0dp</dimen>
</resources> </resources>

View File

@@ -187,6 +187,7 @@
<string name="text_no_brower">没有浏览器耶o(╯□╰)o快去安装一个吧</string> <string name="text_no_brower">没有浏览器耶o(╯□╰)o快去安装一个吧</string>
<string name="text_please_choose_file_to_import">请选择要导入的脚本</string> <string name="text_please_choose_file_to_import">请选择要导入的脚本</string>
<string name="text_refresh">刷新</string> <string name="text_refresh">刷新</string>
<string name="notice_no_running_script"><![CDATA[没有正在运行的脚本 φ(>ω<*)]]></string>
<string-array name="record_control_keys"> <string-array name="record_control_keys">
<item></item> <item></item>

View File

@@ -26,8 +26,8 @@ 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.0'
testCompile 'junit:junit:4.12' testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:25.3.0'
compile 'com.github.hyb1996:node-android-lib:1.0.13' compile 'com.github.hyb1996:node-android-lib:1.0.13'
compile project(path: ':common') compile project(path: ':common')
compile project(path: ':automator') compile project(path: ':automator')

View File

@@ -7,12 +7,10 @@ import java.io.Serializable;
*/ */
public class ExecutionConfig implements Serializable { public class ExecutionConfig implements Serializable {
private static final ExecutionConfig RUNNING_CONFIG = new ExecutionConfig(); private static final ExecutionConfig DEFAULT = new ExecutionConfig();
public String path;
public String prepareScript = "";
public static ExecutionConfig getDefault() { public static ExecutionConfig getDefault() {
return RUNNING_CONFIG; return DEFAULT;
} }
public boolean runInNewThread = true; public boolean runInNewThread = true;
@@ -22,13 +20,4 @@ public class ExecutionConfig implements Serializable {
return this; return this;
} }
public ExecutionConfig path(String path) {
this.path = path;
return this;
}
public ExecutionConfig prepareScript(String script) {
this.prepareScript = script;
return this;
}
} }

View File

@@ -3,17 +3,16 @@ package com.stardust.autojs;
import android.content.Context; import android.content.Context;
import com.stardust.autojs.engine.JavaScriptEngine; import com.stardust.autojs.engine.JavaScriptEngine;
import com.stardust.autojs.engine.JavaScriptEngineManager;
import com.stardust.autojs.engine.ScriptExecuteActivity; import com.stardust.autojs.engine.ScriptExecuteActivity;
import com.stardust.autojs.engine.ScriptExecutionListener;
import com.stardust.autojs.engine.ScriptExecutionTask;
import com.stardust.autojs.script.ScriptSource;
import com.stardust.autojs.engine.SimpleScriptExecutionListener;
import com.stardust.autojs.runtime.ScriptRuntime; import com.stardust.autojs.runtime.ScriptRuntime;
import com.stardust.autojs.runtime.api.Console; import com.stardust.autojs.runtime.api.Console;
import com.stardust.autojs.engine.JavaScriptEngineManager; import com.stardust.autojs.script.ScriptSource;
import java.text.DateFormat; import java.text.DateFormat;
import java.util.Date; import java.util.Date;
import java.util.LinkedHashSet;
import java.util.Set;
/** /**
* Created by Stardust on 2017/1/23. * Created by Stardust on 2017/1/23.
@@ -31,10 +30,11 @@ public class ScriptEngineService {
instance = service; instance = service;
} }
private ScriptRuntime mRuntime; private final ScriptRuntime mRuntime;
private Context mContext; private final Context mContext;
private Console mConsole; private final Console mConsole;
private final JavaScriptEngineManager mJavaScriptEngineManager; private final JavaScriptEngineManager mJavaScriptEngineManager;
private final EngineLifecycleObserver mEngineLifecycleObserver = new EngineLifecycleObserver();
private final ScriptExecutionListener mDefaultListener = new SimpleScriptExecutionListener() { private final ScriptExecutionListener mDefaultListener = new SimpleScriptExecutionListener() {
@Override @Override
@@ -57,16 +57,13 @@ public class ScriptEngineService {
mContext = builder.mContext; mContext = builder.mContext;
mJavaScriptEngineManager = builder.mJavaScriptEngineManager; mJavaScriptEngineManager = builder.mJavaScriptEngineManager;
mConsole = builder.mConsole; mConsole = builder.mConsole;
mJavaScriptEngineManager.setEngineLifecycleCallback(mEngineLifecycleObserver);
} }
public ScriptRuntime getRuntime() { public ScriptRuntime getRuntime() {
return mRuntime; return mRuntime;
} }
public JavaScriptEngineManager getJavaScriptEngineManager() {
return mJavaScriptEngineManager;
}
public Console getConsole() { public Console getConsole() {
return mConsole; return mConsole;
} }
@@ -79,6 +76,14 @@ public class ScriptEngineService {
return mJavaScriptEngineManager.createEngine(); return mJavaScriptEngineManager.createEngine();
} }
public void registerEngineLifecycleCallback(JavaScriptEngineManager.EngineLifecycleCallback engineLifecycleCallback) {
mEngineLifecycleObserver.registerCallback(engineLifecycleCallback);
}
public void unregisterEngineLifecycleCallback(JavaScriptEngineManager.EngineLifecycleCallback engineLifecycleCallback) {
mEngineLifecycleObserver.unregisterCallback(engineLifecycleCallback);
}
public static boolean causedByInterruptedException(Throwable e) { public static boolean causedByInterruptedException(Throwable e) {
while (e != null) { while (e != null) {
if (e instanceof InterruptedException) { if (e instanceof InterruptedException) {
@@ -89,19 +94,34 @@ public class ScriptEngineService {
return false; return false;
} }
public void execute(ScriptExecutionTask task) { public ScriptExecution execute(ScriptExecutionTask task) {
ScriptExecutionListener listener = task.getExecutionListenerOrDefault(mDefaultListener); ScriptExecutionListener listener = task.getExecutionListenerOrDefault(mDefaultListener);
ScriptSource source = task.getScriptSource(); ScriptSource source = task.getSource();
int mode = source.getExecutionMode(); int mode = source.getExecutionMode();
if ((mode & ScriptSource.EXECUTION_MODE_UI) != 0) { if ((mode & ScriptSource.EXECUTION_MODE_UI) != 0) {
ScriptExecuteActivity.execute(mContext, task); ScriptExecuteActivity.execute(mContext, task);
return null;
} else { } else {
new Thread(new ScriptExecution(source, listener, task.getExecutionConfig())).start(); RunnableScriptExecution scriptExecution = new RunnableScriptExecution(source, listener, task.getConfig());
if (task.getConfig().runInNewThread) {
new Thread(scriptExecution).start();
} else {
scriptExecution.run();
}
return scriptExecution;
} }
} }
public void execute(ScriptSource source, ScriptExecutionListener listener, ExecutionConfig config) { public ScriptExecution execute(ScriptSource source, ScriptExecutionListener listener, ExecutionConfig config) {
execute(new ScriptExecutionTask(source, listener, config)); return execute(new ScriptExecutionTask(source, listener, config));
}
public ScriptExecution execute(ScriptSource source, ScriptExecutionListener listener) {
return execute(source, listener, ExecutionConfig.getDefault());
}
public ScriptExecution execute(ScriptSource source) {
return execute(source, mDefaultListener, ExecutionConfig.getDefault());
} }
public int stopAll() { public int stopAll() {
@@ -117,24 +137,71 @@ public class ScriptEngineService {
mRuntime.toast(mContext.getString(R.string.text_no_running_script)); mRuntime.toast(mContext.getString(R.string.text_no_running_script));
} }
public void execute(ScriptSource source, ScriptExecutionListener listener) { public String[] getGlobalFunctions() {
execute(source, listener, ExecutionConfig.getDefault()); return mJavaScriptEngineManager.getGlobalFunctions();
} }
public void execute(ScriptSource source) { public Set<JavaScriptEngine> getEngines() {
execute(source, mDefaultListener, ExecutionConfig.getDefault()); return mJavaScriptEngineManager.getEngines();
} }
private class ScriptExecution extends ScriptExecutionTask implements Runnable { private class RunnableScriptExecution extends ScriptExecutionTask implements ScriptExecution, Runnable {
public ScriptExecution(ScriptSource source, ScriptExecutionListener listener, ExecutionConfig config) { private JavaScriptEngine mJavaScriptEngine;
RunnableScriptExecution(ScriptSource source, ScriptExecutionListener listener, ExecutionConfig config) {
super(source, listener, config); super(source, listener, config);
} }
@Override @Override
public void run() { public void run() {
execute(mRuntime, mJavaScriptEngineManager.createEngine()); mJavaScriptEngine = createScriptEngine();
execute(mRuntime, mJavaScriptEngine);
} }
@Override
public JavaScriptEngine getEngine() {
return mJavaScriptEngine;
}
@Override
public ScriptRuntime getRuntime() {
return mRuntime;
}
}
private static class EngineLifecycleObserver implements JavaScriptEngineManager.EngineLifecycleCallback {
private final Set<JavaScriptEngineManager.EngineLifecycleCallback> mEngineLifecycleCallbacks = new LinkedHashSet<>();
@Override
public void onEngineCreate(JavaScriptEngine engine) {
synchronized (mEngineLifecycleCallbacks) {
for (JavaScriptEngineManager.EngineLifecycleCallback callback : mEngineLifecycleCallbacks) {
callback.onEngineCreate(engine);
}
}
}
@Override
public void onEngineRemove(JavaScriptEngine engine) {
synchronized (mEngineLifecycleCallbacks) {
for (JavaScriptEngineManager.EngineLifecycleCallback callback : mEngineLifecycleCallbacks) {
callback.onEngineRemove(engine);
}
}
}
void registerCallback(JavaScriptEngineManager.EngineLifecycleCallback callback) {
synchronized (mEngineLifecycleCallbacks) {
mEngineLifecycleCallbacks.add(callback);
}
}
void unregisterCallback(JavaScriptEngineManager.EngineLifecycleCallback callback) {
synchronized (mEngineLifecycleCallbacks) {
mEngineLifecycleCallbacks.remove(callback);
}
}
} }
} }

View File

@@ -0,0 +1,22 @@
package com.stardust.autojs;
import com.stardust.autojs.engine.JavaScriptEngine;
import com.stardust.autojs.runtime.ScriptRuntime;
import com.stardust.autojs.script.ScriptSource;
/**
* Created by Stardust on 2017/4/3.
*/
public interface ScriptExecution {
JavaScriptEngine getEngine();
ScriptRuntime getRuntime();
ScriptSource getSource();
ScriptExecutionListener getListener();
ExecutionConfig getConfig();
}

View File

@@ -1,5 +1,6 @@
package com.stardust.autojs.engine; package com.stardust.autojs;
import com.stardust.autojs.engine.JavaScriptEngine;
import com.stardust.autojs.script.ScriptSource; import com.stardust.autojs.script.ScriptSource;
import java.io.Serializable; import java.io.Serializable;

View File

@@ -1,6 +1,6 @@
package com.stardust.autojs.engine; package com.stardust.autojs;
import com.stardust.autojs.ExecutionConfig; import com.stardust.autojs.engine.JavaScriptEngine;
import com.stardust.autojs.runtime.ScriptRuntime; import com.stardust.autojs.runtime.ScriptRuntime;
import com.stardust.autojs.script.ScriptSource; import com.stardust.autojs.script.ScriptSource;
@@ -22,15 +22,15 @@ public class ScriptExecutionTask implements Serializable {
mExecutionConfig = config; mExecutionConfig = config;
} }
public ScriptSource getScriptSource() { public ScriptSource getSource() {
return mScriptSource; return mScriptSource;
} }
public ScriptExecutionListener getExecutionListener() { public ScriptExecutionListener getListener() {
return mExecutionListener; return mExecutionListener;
} }
public ExecutionConfig getExecutionConfig() { public ExecutionConfig getConfig() {
return mExecutionConfig; return mExecutionConfig;
} }
@@ -41,9 +41,10 @@ public class ScriptExecutionTask implements Serializable {
} }
mExecutionListener.onStart(engine, mScriptSource); mExecutionListener.onStart(engine, mScriptSource);
mExecutionListener.onSuccess(engine, mScriptSource, engine.execute(mScriptSource)); mExecutionListener.onSuccess(engine, mScriptSource, engine.execute(mScriptSource));
engine.stop();
} catch (Exception e) { } catch (Exception e) {
mExecutionListener.onException(engine, mScriptSource, e); mExecutionListener.onException(engine, mScriptSource, e);
} finally {
engine.destroy();
} }
} }

View File

@@ -1,5 +1,7 @@
package com.stardust.autojs.engine; package com.stardust.autojs;
import com.stardust.autojs.ScriptExecutionListener;
import com.stardust.autojs.engine.JavaScriptEngine;
import com.stardust.autojs.script.ScriptSource; import com.stardust.autojs.script.ScriptSource;
/** /**

View File

@@ -4,19 +4,31 @@ import com.stardust.autojs.script.ScriptSource;
/** /**
* Created by Stardust on 2017/4/2. * Created by Stardust on 2017/4/2.
* <p>
* <p>
* A JavaScriptEngine is created by {@link JavaScriptEngineManager#createEngine()}, and then can be
* used to execute script with {@link JavaScriptEngine#execute(ScriptSource)} in the **same** thread.
* When the execution finish successfully, the engine should be destroy in the thread that created it.
* <p>
* If you want to stop the engine in other threads, you should call {@link JavaScriptEngine#forceStop()}.
* It will throw a {@link com.stardust.autojs.runtime.ScriptStopException}.
*/ */
public interface JavaScriptEngine { public interface JavaScriptEngine {
void put(String name, Object value); void put(String name, Object value);
Object execute(ScriptSource scriptSource); Object execute(ScriptSource scriptSource);
void stop(); ScriptSource getExecutedScript();
void stopNotRemoveFromManager(); void forceStop();
void destroy(); void destroy();
/**
* @hide
*/
void init(); void init();
} }

View File

@@ -1,10 +1,10 @@
package com.stardust.autojs.engine; package com.stardust.autojs.engine;
import android.content.Context; import android.content.Context;
import android.util.Log;
import com.stardust.autojs.BuildConfig; import com.stardust.autojs.BuildConfig;
import com.stardust.autojs.script.ScriptSource; import com.stardust.autojs.script.ScriptSource;
import com.stardust.autojs.script.StringScriptSource;
import com.stardust.pio.PFile; import com.stardust.pio.PFile;
import java.io.IOException; import java.io.IOException;
@@ -19,19 +19,26 @@ import java.util.Set;
public abstract class JavaScriptEngineManager { public abstract class JavaScriptEngineManager {
public interface EngineLifecycleCallback {
void onEngineCreate(JavaScriptEngine engine);
void onEngineRemove(JavaScriptEngine engine);
}
private static final String TAG = "JavaScriptEngineManager"; private static final String TAG = "JavaScriptEngineManager";
private Map<String, Object> mGlobalVariableMap = new HashMap<>(); private Map<String, Object> mGlobalVariableMap = new HashMap<>();
private final Set<JavaScriptEngine> mEngines = new HashSet<>(); private final Set<JavaScriptEngine> mEngines = new HashSet<>();
private boolean mIsStopping = false; private boolean mIsStopping = false;
private EngineLifecycleCallback mEngineLifecycleCallback;
private final ScriptSource INIT_SCRIPT; private final ScriptSource INIT_SCRIPT;
private android.content.Context mContext; private android.content.Context mContext;
public JavaScriptEngineManager(Context context) { public JavaScriptEngineManager(Context context) {
mContext = context; mContext = context;
INIT_SCRIPT = ScriptSource.of(readInitScript()); INIT_SCRIPT = new StringScriptSource(readInitScript());
} }
public JavaScriptEngine createEngine() { public JavaScriptEngine createEngine() {
@@ -40,6 +47,9 @@ public abstract class JavaScriptEngineManager {
engine.init(); engine.init();
synchronized (mEngines) { synchronized (mEngines) {
mEngines.add(engine); mEngines.add(engine);
if(mEngineLifecycleCallback != null){
mEngineLifecycleCallback.onEngineCreate(engine);
}
} }
return engine; return engine;
} }
@@ -48,6 +58,14 @@ public abstract class JavaScriptEngineManager {
mGlobalVariableMap.put(varName, value); mGlobalVariableMap.put(varName, value);
} }
public void setEngineLifecycleCallback(EngineLifecycleCallback engineLifecycleCallback) {
mEngineLifecycleCallback = engineLifecycleCallback;
}
public Set<JavaScriptEngine> getEngines() {
return mEngines;
}
protected abstract JavaScriptEngine createEngineInner(); protected abstract JavaScriptEngine createEngineInner();
public abstract String[] getGlobalFunctions(); public abstract String[] getGlobalFunctions();
@@ -62,11 +80,14 @@ public abstract class JavaScriptEngineManager {
} }
} }
void removeEngine(RhinoJavaScriptEngine rhinoJavaScriptEngine) { void removeEngine(JavaScriptEngine engine) {
synchronized (mEngines) { synchronized (mEngines) {
if (mIsStopping) if (mIsStopping)
return; return;
mEngines.remove(rhinoJavaScriptEngine); mEngines.remove(engine);
if(mEngineLifecycleCallback != null){
mEngineLifecycleCallback.onEngineRemove(engine);
}
} }
} }
@@ -81,7 +102,7 @@ public abstract class JavaScriptEngineManager {
public ScriptSource getInitScript() { public ScriptSource getInitScript() {
if (BuildConfig.DEBUG) { if (BuildConfig.DEBUG) {
// 调试时不缓存INIT_SCRIPT否则修改javascript_engine_init.js后不会更新 // 调试时不缓存INIT_SCRIPT否则修改javascript_engine_init.js后不会更新
return ScriptSource.of(readInitScript()); return new StringScriptSource(readInitScript());
} else { } else {
return INIT_SCRIPT; return INIT_SCRIPT;
} }
@@ -93,7 +114,10 @@ public abstract class JavaScriptEngineManager {
mIsStopping = true; mIsStopping = true;
int n = mEngines.size(); int n = mEngines.size();
for (JavaScriptEngine engine : mEngines) { for (JavaScriptEngine engine : mEngines) {
engine.stopNotRemoveFromManager(); engine.forceStop();
if(mEngineLifecycleCallback != null){
mEngineLifecycleCallback.onEngineRemove(engine);
}
} }
mEngines.clear(); mEngines.clear();
mIsStopping = false; mIsStopping = false;

View File

@@ -23,6 +23,7 @@ public class RhinoJavaScriptEngine implements JavaScriptEngine {
private Scriptable mScriptable; private Scriptable mScriptable;
private Thread mThread; private Thread mThread;
private RhinoJavaScriptEngineManager mEngineManager; private RhinoJavaScriptEngineManager mEngineManager;
private ScriptSource mScriptSource;
public RhinoJavaScriptEngine(RhinoJavaScriptEngineManager engineManager) { public RhinoJavaScriptEngine(RhinoJavaScriptEngineManager engineManager) {
mEngineManager = engineManager; mEngineManager = engineManager;
@@ -38,22 +39,17 @@ public class RhinoJavaScriptEngine implements JavaScriptEngine {
@Override @Override
public Object execute(ScriptSource source) { public Object execute(ScriptSource source) {
try { mScriptSource = source;
return mContext.evaluateString(mScriptable, source.getScript(), "<script>", 1, null); return mContext.evaluateString(mScriptable, source.getScript(), "<script>", 1, null);
} catch (Exception e) {
stop();
throw e;
}
} }
@Override @Override
public void stop() { public ScriptSource getExecutedScript() {
mEngineManager.removeEngine(this); return mScriptSource;
stopNotRemoveFromManager();
} }
@Override @Override
public void stopNotRemoveFromManager() { public void forceStop() {
mThread.interrupt(); mThread.interrupt();
} }
@@ -63,7 +59,8 @@ public class RhinoJavaScriptEngine implements JavaScriptEngine {
@Override @Override
public void destroy() { public void destroy() {
Context.exit();
mEngineManager.removeEngine(this);
} }
@Override @Override
@@ -99,8 +96,7 @@ public class RhinoJavaScriptEngine implements JavaScriptEngine {
@Override @Override
protected void observeInstructionCount(Context cx, int instructionCount) { protected void observeInstructionCount(Context cx, int instructionCount) {
if (Thread.currentThread().isInterrupted()) { if (Thread.currentThread().isInterrupted()) {
Context.exit(); throw new ScriptStopException(new InterruptedException());
throw new ScriptStopException();
} }
} }

View File

@@ -3,6 +3,7 @@ package com.stardust.autojs.engine;
import com.stardust.autojs.runtime.ScriptRuntime; import com.stardust.autojs.runtime.ScriptRuntime;
import com.stardust.autojs.script.ScriptSource; import com.stardust.autojs.script.ScriptSource;
import com.stardust.autojs.script.StringScriptSource;
import org.mozilla.javascript.Context; import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable; import org.mozilla.javascript.Scriptable;
@@ -64,13 +65,13 @@ public class RhinoJavaScriptEngineManager extends JavaScriptEngineManager {
private String[] getGlobalFunctionsInner() { private String[] getGlobalFunctionsInner() {
JavaScriptEngine engine = createEngine(); JavaScriptEngine engine = createEngine();
Scriptable scriptable = (Scriptable) engine.execute(ScriptSource.of("this")); Scriptable scriptable = (Scriptable) engine.execute(new StringScriptSource("this"));
Object[] ids = scriptable.getIds(); Object[] ids = scriptable.getIds();
String[] functions = new String[ids.length]; String[] functions = new String[ids.length];
for (int i = 0; i < ids.length; i++) { for (int i = 0; i < ids.length; i++) {
functions[i] = ids[i].toString(); functions[i] = ids[i].toString();
} }
engine.stop(); engine.destroy();
return functions; return functions;
} }

View File

@@ -6,6 +6,8 @@ import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import com.stardust.autojs.ScriptEngineService; import com.stardust.autojs.ScriptEngineService;
import com.stardust.autojs.ScriptExecutionListener;
import com.stardust.autojs.ScriptExecutionTask;
import com.stardust.autojs.script.ScriptSource; import com.stardust.autojs.script.ScriptSource;
/** /**
@@ -37,8 +39,8 @@ public class ScriptExecuteActivity extends Activity {
private void handleIntent(Intent intent) { private void handleIntent(Intent intent) {
ScriptExecutionTask scriptExecutionTask = (ScriptExecutionTask) intent.getSerializableExtra(EXTRA_TASK); ScriptExecutionTask scriptExecutionTask = (ScriptExecutionTask) intent.getSerializableExtra(EXTRA_TASK);
mExecutionListener = scriptExecutionTask.getExecutionListener(); mExecutionListener = scriptExecutionTask.getListener();
mScriptSource = scriptExecutionTask.getScriptSource(); mScriptSource = scriptExecutionTask.getSource();
} }
private void runScript() { private void runScript() {
@@ -61,7 +63,7 @@ public class ScriptExecuteActivity extends Activity {
protected void onDestroy() { protected void onDestroy() {
super.onDestroy(); super.onDestroy();
mJavaScriptEngine.put("activity", null); mJavaScriptEngine.put("activity", null);
mJavaScriptEngine.stop(); mJavaScriptEngine.destroy();
} }
} }

View File

@@ -15,6 +15,7 @@ public class FileScriptSource extends ScriptSource {
private String mScript; private String mScript;
public FileScriptSource(File file) { public FileScriptSource(File file) {
super(PFile.getNameWithoutExtension(file.getName()));
mFile = file; mFile = file;
} }
@@ -22,6 +23,11 @@ public class FileScriptSource extends ScriptSource {
this(new File(path)); this(new File(path));
} }
public FileScriptSource(String name, File file) {
super(name);
mFile = file;
}
@Override @Override
public String getScript() { public String getScript() {
if (mScript == null) if (mScript == null)

View File

@@ -7,14 +7,16 @@ package com.stardust.autojs.script;
public class MultiScriptSource extends ScriptSource { public class MultiScriptSource extends ScriptSource {
private String mScript; private String mScript;
private FileScriptSource mFileScriptSource;
public MultiScriptSource(ScriptSource... sources) {
public MultiScriptSource(StringScriptSource stringScriptSource, FileScriptSource fileScriptSource) {
super(fileScriptSource.getName());
mFileScriptSource = fileScriptSource;
StringBuilder stringBuilder = new StringBuilder(); StringBuilder stringBuilder = new StringBuilder();
for (ScriptSource source : sources) { if (stringScriptSource.getScript() != null)
String script = source.getScript(); stringBuilder.append(stringScriptSource.getScript()).append("\n");
if (script != null) stringBuilder.append(fileScriptSource.getScript());
stringBuilder.append(script).append("\n");
}
mScript = stringBuilder.toString(); mScript = stringBuilder.toString();
} }
@@ -22,4 +24,10 @@ public class MultiScriptSource extends ScriptSource {
public String getScript() { public String getScript() {
return mScript; return mScript;
} }
@Override
public String toString() {
return mFileScriptSource.toString();
}
} }

View File

@@ -26,7 +26,15 @@ public abstract class ScriptSource implements Serializable {
private static final int EXECUTION_MODE_STRING_MAX_LENGTH = 7; private static final int EXECUTION_MODE_STRING_MAX_LENGTH = 7;
private int mExecutionMode = -1; private int mExecutionMode = -1;
private String mName;
public ScriptSource(String name) {
mName = name;
}
public String getName() {
return mName;
}
public abstract String getScript(); public abstract String getScript();
@@ -38,7 +46,7 @@ public abstract class ScriptSource implements Serializable {
} }
private int parseExecutionMode(String script) { private int parseExecutionMode(String script) {
if (script.charAt(0) != '"') if (script == null || script.length() == 0 || script.charAt(0) != '"')
return EXECUTION_MODE_NORMAL; return EXECUTION_MODE_NORMAL;
int i = script.lastIndexOf("\";", EXECUTION_MODE_STRING_MAX_LENGTH + 2); int i = script.lastIndexOf("\";", EXECUTION_MODE_STRING_MAX_LENGTH + 2);
if (i == -1) if (i == -1)
@@ -58,7 +66,4 @@ public abstract class ScriptSource implements Serializable {
return mode; return mode;
} }
public static ScriptSource of(String script) {
return new StringScriptSource(script);
}
} }

View File

@@ -10,6 +10,12 @@ public class StringScriptSource extends ScriptSource {
private String mScript; private String mScript;
public StringScriptSource(String script) { public StringScriptSource(String script) {
super("Tmp");
mScript = script;
}
public StringScriptSource(String name, String script) {
super(name);
mScript = script; mScript = script;
} }

View File

@@ -7,7 +7,6 @@ import android.view.accessibility.AccessibilityNodeInfo;
import com.stardust.util.Consumer; import com.stardust.util.Consumer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator;
import java.util.List; import java.util.List;
import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.*; import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.*;

View File

@@ -28,5 +28,4 @@ dependencies {
}) })
compile 'com.android.support:appcompat-v7:25.3.0' compile 'com.android.support:appcompat-v7:25.3.0'
testCompile 'junit:junit:4.12' testCompile 'junit:junit:4.12'
compile 'org.testng:testng:6.9.6'
} }

View File

@@ -1,6 +1,7 @@
package com.stardust.pio; package com.stardust.pio;
import android.content.Context; import android.content.Context;
import android.util.Log;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
@@ -16,6 +17,8 @@ import java.io.OutputStream;
public class PFile { public class PFile {
private static final String TAG = "PFile";
private static final int BUFFER_SIZE = 8192; private static final int BUFFER_SIZE = 8192;
public static PFile open(String path, String mode) { public static PFile open(String path, String mode) {
@@ -203,12 +206,11 @@ public class PFile {
int a = fileName.lastIndexOf('/'); int a = fileName.lastIndexOf('/');
if (a < 0) if (a < 0)
a = fileName.lastIndexOf('\\'); a = fileName.lastIndexOf('\\');
int b = fileName.lastIndexOf('.');
if (a < 0) if (a < 0)
a = -1; a = -1;
int b = fileName.indexOf('.', a + 1);
if (b < 0) if (b < 0)
b = fileName.length(); b = fileName.length();
// FIXME: 2017/4/3 StringOutOfBoundsException
fileName = fileName.substring(a + 1, b); fileName = fileName.substring(a + 1, b);
return fileName; return fileName;
} }

View File

@@ -1,8 +1,5 @@
package com.stardust.util; package com.stardust.util;
import org.junit.Assert;
import org.junit.Test;
import java.io.File; import java.io.File;
import java.util.Arrays; import java.util.Arrays;
import java.util.Comparator; import java.util.Comparator;
@@ -24,56 +21,4 @@ public class FileSorter {
}); });
} }
public static class TestSuite {
@Test
public void testEngFileSort() {
File file1 = new File("d:/a.txt");
File file2 = new File("e:/b.txt");
File file3 = new File("c:/c.txt");
File[] files = {file2, file3, file1};
sort(files);
Assert.assertArrayEquals(new File[]{file1, file2, file3}, files);
}
@Test
public void testEngFileSortWithDirectory() {
File dir1 = new File("d:/");
File dir2 = new File("e:/");
File file1 = new File("e:/a.txt");
File file2 = new File("e:/b.txt");
File file3 = new File("d:/c.txt");
Assert.assertTrue(dir1.isDirectory());
Assert.assertTrue(dir2.isDirectory());
File[] files = {file2, file3, dir1, file1, dir2};
sort(files);
Assert.assertArrayEquals(new File[]{dir1, dir2, file1, file2, file3}, files);
}
@Test
public void testCnFileSort() {
File file1 = new File("a.txt");
File file2 = new File("b.txt");
File file3 = new File("啊.txt");
File file4 = new File("啊啊.txt");
File[] files = {file2, file4, file3, file1};
sort(files);
Assert.assertArrayEquals(new File[]{file1, file2, file3, file4}, files);
}
@Test
public void testCnFileSortWithDirectory() {
File dir1 = new File("d:/整理/");
File dir2 = new File("d:/迅雷下载/");
File file1 = new File("d:/整理/a.txt");
File file2 = new File("啊.txt");
File file3 = new File("啊啊.txt");
Assert.assertTrue(dir1.isDirectory());
Assert.assertTrue(dir2.isDirectory());
File[] files = {file2, file3, dir1, file1, dir2};
sort(files);
Assert.assertArrayEquals(new File[]{dir1, dir2, file1, file2, file3}, files);
}
}
} }

View File

@@ -1,12 +1,7 @@
package com.stardust.util; package com.stardust.util;
import org.junit.Test;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/** /**
* Created by Stardust on 2017/3/31. * Created by Stardust on 2017/3/31.
*/ */
@@ -26,33 +21,4 @@ public class LimitedHashMap<K, V> extends LinkedHashMap<K, V> {
} }
public static class TestSuite {
@org.testng.annotations.Test
public void testAutoRemove() {
LimitedHashMap<String, Integer> hashMap = new LimitedHashMap<>(5);
hashMap.put("a", 1);
hashMap.put("b", 2);
hashMap.put("c", 3);
hashMap.put("d", 4);
hashMap.put("e", 5);
hashMap.put("f", 6);
assertFalse(hashMap.containsKey("a"));
}
@Test
public void testAutoReorder() {
LimitedHashMap<String, Integer> hashMap = new LimitedHashMap<>(5);
hashMap.put("a", 1);
hashMap.put("b", 2);
hashMap.put("c", 3);
hashMap.put("d", 4);
hashMap.put("e", 5);
hashMap.get("a");
hashMap.put("f", 6);
assertTrue(hashMap.containsKey("a"));
assertFalse(hashMap.containsKey("b"));
}
}
} }

View File

@@ -1,12 +1,5 @@
package com.stardust.util; package com.stardust.util;
import android.os.Build;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
/** /**
* Created by Stardust on 2017/4/3. * Created by Stardust on 2017/4/3.
*/ */
@@ -27,14 +20,5 @@ public class SdkVersionUtil {
return SDK_VERSIONS[i - 1]; return SDK_VERSIONS[i - 1];
} }
public static final class TestSuite {
@Test
public void test() {
assertEquals("5.0", sdkIntToString(21));
assertEquals("8.0", sdkIntToString(26));
assertEquals("Unknown", sdkIntToString(27));
}
}
} }

View File

@@ -3,6 +3,8 @@ package com.stardust.util;
import android.content.Context; import android.content.Context;
import android.support.annotation.IdRes; import android.support.annotation.IdRes;
import android.view.View; import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
/** /**
* Created by Stardust on 2017/1/24. * Created by Stardust on 2017/1/24.
@@ -23,4 +25,6 @@ public class ViewUtil {
} }
return result; return result;
} }
} }