diff --git a/.idea/codeStyleSettings.xml b/.idea/codeStyleSettings.xml new file mode 100644 index 00000000..719bb8bc --- /dev/null +++ b/.idea/codeStyleSettings.xml @@ -0,0 +1,228 @@ + + + + + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 94235db1..75d6bb69 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -118,6 +118,9 @@ dependencies { compile 'com.yqritc:recyclerview-flexibledivider:1.4.0' compile 'com.ashokvarma.android:bottom-navigation-bar:2.0.1' compile 'com.wang.avi:library:2.1.3' + compile "io.reactivex.rxjava2:rxjava:2.1.0" + compile 'io.reactivex.rxjava2:rxandroid:2.0.1' + // Tasker Plugin compile 'com.twofortyfouram:android-plugin-client-sdk-for-locale:[4.0.2, 5.0[' compile 'com.android.volley:volley:1.0.0' diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/common/ScriptOperations.java b/app/src/main/java/com/stardust/scriptdroid/ui/common/ScriptOperations.java new file mode 100644 index 00000000..dc275fe1 --- /dev/null +++ b/app/src/main/java/com/stardust/scriptdroid/ui/common/ScriptOperations.java @@ -0,0 +1,252 @@ +package com.stardust.scriptdroid.ui.common; + +import android.app.Activity; +import android.support.annotation.NonNull; +import android.support.design.widget.Snackbar; +import android.support.v4.widget.DrawerLayout; +import android.text.InputType; +import android.util.Log; +import android.view.View; +import android.widget.EditText; + +import com.afollestad.materialdialogs.DialogAction; +import com.afollestad.materialdialogs.MaterialDialog; +import com.stardust.pio.PFile; +import com.stardust.pio.UncheckedIOException; +import com.stardust.scriptdroid.R; +import com.stardust.scriptdroid.script.ScriptFile; +import com.stardust.scriptdroid.script.Scripts; +import com.stardust.scriptdroid.script.StorageScriptProvider; +import com.stardust.scriptdroid.script.sample.Sample; +import com.stardust.scriptdroid.ui.edit.EditActivity; +import com.stardust.scriptdroid.ui.main.MainActivity; +import com.stardust.scriptdroid.ui.main.script_list.MyScriptListFragment; +import com.stardust.theme.dialog.ThemeColorMaterialDialogBuilder; +import com.stardust.util.UnderuseExecutors; + +import org.reactivestreams.Publisher; +import org.reactivestreams.Subscriber; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; + +import io.reactivex.Observable; +import io.reactivex.ObservableEmitter; +import io.reactivex.ObservableOnSubscribe; +import io.reactivex.Scheduler; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.functions.Consumer; +import io.reactivex.functions.Function; +import io.reactivex.schedulers.Schedulers; +import io.reactivex.subjects.PublishSubject; + +/** + * Created by Stardust on 2017/7/31. + */ + +public class ScriptOperations { + + private Activity mActivity; + private View mView; + private ScriptFile mCurrentDirectory; + + public ScriptOperations(Activity activity, View view, ScriptFile currentDirectory) { + mActivity = activity; + mView = view; + mCurrentDirectory = currentDirectory; + } + + public ScriptOperations(Activity activity, View view) { + this(activity, view, MyScriptListFragment.getCurrentDirectory()); + } + + public void newScriptFileForScript(final String script) { + showFileNameInputDialog("") + .subscribe(new Consumer() { + @Override + public void accept(@io.reactivex.annotations.NonNull String input) throws Exception { + createScriptFile(getCurrentDirectoryPath() + input + ".js", script); + } + }); + } + + private String getCurrentDirectoryPath() { + return getCurrentDirectory().getPath() + "/"; + } + + private ScriptFile getCurrentDirectory() { + return mCurrentDirectory; + } + + public void createScriptFile(String path, String script) { + if (PFile.createIfNotExists(path)) { + if (script != null) { + try { + PFile.write(path, script); + } catch (UncheckedIOException e) { + Snackbar.make(mView, R.string.text_file_write_fail, Snackbar.LENGTH_LONG).show(); + } + } + notifyScriptFileChanged(); + Scripts.edit(path); + } else { + Snackbar.make(mView, R.string.text_create_fail, Snackbar.LENGTH_LONG).show(); + } + } + + public void newScriptFile() { + newScriptFileForScript(null); + } + + public Observable importFile(final String pathFrom) { + try { + return importFile(PFile.getNameWithoutExtension(pathFrom), new FileInputStream(pathFrom)); + } catch (FileNotFoundException e) { + showMessage(R.string.file_not_exists); + return Observable.error(e); + } + } + + public Observable importFile(String prefix, final InputStream inputStream) { + return showFileNameInputDialog(PFile.getNameWithoutExtension(prefix)) + .observeOn(Schedulers.io()) + .map(new Function() { + @Override + public String apply(@io.reactivex.annotations.NonNull String s) throws Exception { + final String pathTo = getCurrentDirectoryPath() + s + ".js"; + if (PFile.copyStream(inputStream, pathTo)) { + showMessage(R.string.text_import_succeed); + } else { + showMessage(R.string.text_import_fail); + } + notifyScriptFileChanged(); + return pathTo; + } + }); + } + + + public void newDirectory() { + showNameInputDialog("", new InputCallback(true)) + .subscribe(new Consumer() { + @Override + public void accept(@io.reactivex.annotations.NonNull String path) throws Exception { + if (new ScriptFile(getCurrentDirectory(), path).mkdirs()) { + showMessage(R.string.text_already_create); + notifyScriptFileChanged(); + } else { + showMessage(R.string.text_create_fail); + } + } + }); + } + + private void notifyScriptFileChanged() { + StorageScriptProvider.getDefault().notifyDirectoryChanged(mCurrentDirectory); + } + + private void showMessage(final int resId) { + mActivity.runOnUiThread(new Runnable() { + @Override + public void run() { + Snackbar.make(mView, resId, Snackbar.LENGTH_SHORT).show(); + } + }); + } + + + private Observable showFileNameInputDialog(String prefix) { + return showNameInputDialog(prefix, new InputCallback(false)); + } + + private Observable showNameInputDialog(String prefix, MaterialDialog.InputCallback textWatcher) { + final PublishSubject input = PublishSubject.create(); + new ThemeColorMaterialDialogBuilder(mActivity).title(R.string.text_name) + .inputType(InputType.TYPE_CLASS_TEXT) + .alwaysCallInputCallback() + .input(getString(R.string.text_please_input_name), prefix, false, textWatcher) + .onPositive(new MaterialDialog.SingleButtonCallback() { + @Override + public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) { + input.onNext(dialog.getInputEditText().getText().toString()); + input.onComplete(); + } + }) + .show(); + return input; + } + + + private CharSequence getString(int resId) { + return mActivity.getString(resId); + } + + public Observable importSample(Sample sample) { + try { + return importFile(sample.name, mActivity.getAssets().open(sample.path)); + } catch (IOException e) { + e.printStackTrace(); + Snackbar.make(mView, R.string.text_import_fail, Snackbar.LENGTH_SHORT).show(); + return Observable.error(e); + } + } + + public Observable rename(final ScriptFile file) { + String originalName = file.getSimplifiedName(); + return showNameInputDialog(originalName, new InputCallback(file.isDirectory(), originalName)) + .map(new Function() { + @Override + public Boolean apply(@io.reactivex.annotations.NonNull String newName) throws Exception { + return file.renameTo(newName); + } + }); + } + + private class InputCallback implements MaterialDialog.InputCallback { + + private boolean mIsDirectory = false; + private String mExcluded; + private boolean mIsFirstTextChanged = true; + + InputCallback(boolean isDirectory, String excluded) { + mIsDirectory = isDirectory; + mExcluded = excluded; + } + + InputCallback(boolean isDirectory) { + mIsDirectory = isDirectory; + } + + @Override + public void onInput(@NonNull MaterialDialog dialog, CharSequence input) { + if (mIsFirstTextChanged) { + mIsFirstTextChanged = false; + return; + } + EditText editText = dialog.getInputEditText(); + if (editText == null) + return; + int errorResId = 0; + if (input == null || input.length() == 0) { + errorResId = R.string.text_name_should_not_be_empty; + } else if (!input.equals(mExcluded)) { + if (new File(getCurrentDirectory(), mIsDirectory ? input.toString() : input.toString() + ".js").exists()) { + errorResId = R.string.text_file_exists; + } + } + if (errorResId == 0) { + editText.setError(null); + dialog.getActionButton(DialogAction.POSITIVE).setEnabled(true); + } else { + editText.setError(getString(errorResId)); + dialog.getActionButton(DialogAction.POSITIVE).setEnabled(false); + } + + } + } + + +} diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/edit/ViewSampleActivity.java b/app/src/main/java/com/stardust/scriptdroid/ui/edit/ViewSampleActivity.java index 10f10aff..a0bcef59 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/edit/ViewSampleActivity.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/edit/ViewSampleActivity.java @@ -23,6 +23,7 @@ import com.stardust.scriptdroid.autojs.AutoJs; import com.stardust.scriptdroid.script.Scripts; import com.stardust.scriptdroid.script.sample.Sample; import com.stardust.scriptdroid.ui.BaseActivity; +import com.stardust.scriptdroid.ui.common.ScriptOperations; import com.stardust.scriptdroid.ui.edit.editor920.Editor920Activity; import com.stardust.scriptdroid.ui.edit.editor920.Editor920Utils; import com.stardust.scriptdroid.ui.help.HelpCatalogueActivity; @@ -33,11 +34,11 @@ import com.stardust.util.SparseArrayEntries; import com.stardust.widget.ToolbarMenuItem; -import org.androidannotations.annotations.Click; -import org.androidannotations.annotations.EActivity; - import butterknife.ButterKnife; import butterknife.OnClick; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.annotations.NonNull; +import io.reactivex.functions.Consumer; import static com.stardust.scriptdroid.script.Scripts.ACTION_ON_EXECUTION_FINISHED; import static com.stardust.scriptdroid.script.Scripts.EXTRA_EXCEPTION_MESSAGE; @@ -118,6 +119,20 @@ public class ViewSampleActivity extends Editor920Activity implements OnActivityR mScriptExecution = Scripts.runWithBroadcastSender(new StringScriptSource(mSample.name, mEditorDelegate.getText())); } + @OnClick(R.id.edit) + void edit() { + new ScriptOperations(this, mView) + .importSample(mSample) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Consumer() { + @Override + public void accept(@NonNull String path) throws Exception { + EditActivity.editFile(ViewSampleActivity.this, path); + finish(); + } + }); + } + private void initMenuItem() { mMenuMap = new SparseArrayEntries() .entry(R.id.run, (ToolbarMenuItem) findViewById(R.id.run)) @@ -152,7 +167,9 @@ public class ViewSampleActivity extends Editor920Activity implements OnActivityR HelpCatalogueActivity.showMainCatalogue(this); return true; case R.id.action_import: - MainActivity.importSample(this, mSample); + new ScriptOperations(this, mView) + .importSample(mSample) + .subscribe(); return true; } return super.onOptionsItemSelected(item); diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/main/MainActivity.java b/app/src/main/java/com/stardust/scriptdroid/ui/main/MainActivity.java index 636fc974..1a5eefca 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/main/MainActivity.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/main/MainActivity.java @@ -40,6 +40,7 @@ import com.stardust.scriptdroid.external.open.ImportIntentActivity; import com.stardust.scriptdroid.script.ScriptFile; import com.stardust.scriptdroid.script.StorageScriptProvider; import com.stardust.scriptdroid.script.sample.Sample; +import com.stardust.scriptdroid.ui.common.ScriptOperations; import com.stardust.scriptdroid.ui.main.task.TaskManagerFragment_; import com.stardust.util.IntentExtras; import com.stardust.view.accessibility.AccessibilityService; @@ -67,6 +68,7 @@ import org.androidannotations.annotations.ViewById; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; +import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -221,22 +223,14 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega @Click(R.id.create_new_file) void createScriptFile() { - doWithMyScriptListFragment(new Callback() { - @Override - public void call(MyScriptListFragment myScriptListFragment) { - myScriptListFragment.newScriptFile(); - } - }); + new ScriptOperations(this, mDrawerLayout) + .newScriptFile(); } @Click(R.id.create_new_directory) void createNewDirectory() { - doWithMyScriptListFragment(new Callback() { - @Override - public void call(MyScriptListFragment myScriptListFragment) { - myScriptListFragment.newDirectory(); - } - }); + new ScriptOperations(this, mDrawerLayout) + .newDirectory(); } @Click(R.id.import_from_file) @@ -249,12 +243,8 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega public void onFileSelection(MaterialDialog dialog, final ScriptFile file) { dialog.dismiss(); provider.clearCacheExceptInitialDirectory(); - doWithMyScriptListFragment(new Callback() { - @Override - public void call(MyScriptListFragment myScriptListFragment) { - myScriptListFragment.importFile(file.getPath()); - } - }); + new ScriptOperations(MainActivity.this, mDrawerLayout) + .importFile(file.getPath()); } }) .title(R.string.text_please_choose_file_to_import) @@ -324,48 +314,19 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega case ACTION_IMPORT_SCRIPT: handleImportScriptFile(intent); break; - case ACTION_IMPORT_SAMPLE: - handleImportSample(intent); - break; } } private void handleImportScriptFile(Intent intent) { - mViewPager.setCurrentItem(0, true); - MyScriptListFragment fragment = getMyScriptListFragment(); - if (fragment == null) { - mIntentToHandle = intent; - } else { - String path = intent.getStringExtra(ARGUMENT_PATH); - if (path != null) { - fragment.importFile(intent.getStringExtra(ARGUMENT_PATH)); - return; - } - InputStream inputStream = IntentExtras.fromIntent(intent).getAndClear(ARGUMENT_INPUT_STREAM); - fragment.importFile("", inputStream); - } - } - - - private void handleImportSample(Intent intent) { - mViewPager.setCurrentItem(0, true); - MyScriptListFragment fragment = getMyScriptListFragment(); - if (fragment == null) { - mIntentToHandle = intent; - } else { - final Sample sample = (Sample) intent.getSerializableExtra(ARGUMENT_SAMPLE); - doWithMyScriptListFragment(new Callback() { - @Override - public void call(MyScriptListFragment myScriptListFragment) { - try { - myScriptListFragment.importFile(sample.name, getAssets().open(sample.path)); - } catch (IOException e) { - e.printStackTrace(); - Snackbar.make(mDrawerLayout, R.string.text_import_fail, Snackbar.LENGTH_SHORT).show(); - } - } - }); + String path = intent.getStringExtra(ARGUMENT_PATH); + if (path != null) { + new ScriptOperations(MainActivity.this, mDrawerLayout) + .importFile(intent.getStringExtra(ARGUMENT_PATH)); + return; } + InputStream inputStream = IntentExtras.fromIntent(intent).getAndClear(ARGUMENT_INPUT_STREAM); + new ScriptOperations(MainActivity.this, mDrawerLayout) + .importFile("", inputStream); } private void handleRecordedScript(final String script) { @@ -376,12 +337,8 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega @Override public void onSelection(MaterialDialog dialog, View itemView, int position, CharSequence text) { if (position == 0) { - doWithMyScriptListFragment(new Callback() { - @Override - public void call(MyScriptListFragment myScriptListFragment) { - myScriptListFragment.newScriptFileForScript(script); - } - }); + new ScriptOperations(MainActivity.this, mDrawerLayout) + .newScriptFileForScript(script); } else { ((ClipboardManager) getSystemService(CLIPBOARD_SERVICE)) .setPrimaryClip(ClipData.newPlainText("script", script)); @@ -418,39 +375,6 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega context.startActivity(intent); } - public static void importSample(Context context, Sample sample) { - context.startActivity(new Intent(context, MainActivity_.class) - .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP) - .putExtra(EXTRA_ACTION, ACTION_IMPORT_SAMPLE) - .putExtra(ARGUMENT_SAMPLE, sample)); - } - - public void doWithMyScriptListFragment(final Callback callback) { - MyScriptListFragment fragment = ((MyScriptListFragment) mPagerAdapter.getStoredFragment(0)); - if (fragment != null) { - callback.call(fragment); - return; - } - mViewPager.setCurrentItem(0); - mViewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { - @Override - public void onPageSelected(int position) { - if (position == 0) { - mViewPager.removeOnPageChangeListener(this); - doWithMyScriptListFragment(callback); - } - } - }); - } - - @Nullable - public MyScriptListFragment getMyScriptListFragment() { - MyScriptListFragment fragment = ((MyScriptListFragment) mPagerAdapter.getStoredFragment(0)); - if (fragment == null) { - mViewPager.setCurrentItem(0); - } - return ((MyScriptListFragment) mPagerAdapter.getStoredFragment(0)); - } @Click(R.id.toolbar) public void OnToolbarClick() { diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/main/sample_list/SampleScriptListFragment.java b/app/src/main/java/com/stardust/scriptdroid/ui/main/sample_list/SampleScriptListFragment.java index b99f9532..aa1a07ec 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/main/sample_list/SampleScriptListFragment.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/main/sample_list/SampleScriptListFragment.java @@ -12,6 +12,7 @@ import com.stardust.scriptdroid.R; import com.stardust.scriptdroid.script.Scripts; import com.stardust.scriptdroid.script.sample.Sample; import com.stardust.scriptdroid.script.sample.SampleFileManager; +import com.stardust.scriptdroid.ui.common.ScriptOperations; import com.stardust.scriptdroid.ui.edit.ViewSampleActivity; import com.stardust.scriptdroid.ui.main.MainActivity; @@ -66,7 +67,9 @@ public class SampleScriptListFragment extends Fragment { } private void copySampleToMyScripts(Sample sample) { - MainActivity.importSample(getActivity(), sample); + new ScriptOperations(getActivity(), getView()) + .importSample(sample) + .subscribe(); } private void viewSample(Sample sample) { diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/main/script_list/MyScriptListFragment.java b/app/src/main/java/com/stardust/scriptdroid/ui/main/script_list/MyScriptListFragment.java index e21ad312..d64c012b 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/main/script_list/MyScriptListFragment.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/main/script_list/MyScriptListFragment.java @@ -22,11 +22,15 @@ import com.stardust.scriptdroid.R; import com.stardust.scriptdroid.script.Scripts; import com.stardust.scriptdroid.script.StorageScriptProvider; import com.stardust.scriptdroid.ui.common.ScriptLoopDialog; +import com.stardust.scriptdroid.ui.common.ScriptOperations; import com.stardust.scriptdroid.ui.edit.EditActivity; import com.stardust.theme.dialog.ThemeColorMaterialDialogBuilder; import com.stardust.util.UnderuseExecutors; import com.stardust.widget.SimpleAdapterDataObserver; +import org.reactivestreams.Publisher; +import org.reactivestreams.Subscriber; + import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -34,6 +38,10 @@ import java.io.InputStream; import butterknife.OnClick; import butterknife.Optional; +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.functions.Consumer; +import io.reactivex.schedulers.Schedulers; /** * Created by Stardust on 2017/3/13. @@ -45,13 +53,14 @@ public class MyScriptListFragment extends Fragment { private static final String TAG = "MyScriptListFragment"; + private static ScriptFile sCurrentDirectory = StorageScriptProvider.DEFAULT_DIRECTORY; + private ScriptAndFolderListRecyclerView mScriptListRecyclerView; private ScriptListWithProgressBarView mScriptListWithProgressBarView; private View mNoScriptHint; private MaterialDialog mScriptFileOperationDialog; private MaterialDialog mDirectoryOperationDialog; private ScriptFile mSelectedScriptFile; - private String mFilePathToImport; @Nullable @Override @@ -68,10 +77,6 @@ public class MyScriptListFragment extends Fragment { mNoScriptHint = $(R.id.hint_no_script); initScriptListRecyclerView(); initDialogs(); - if (mFilePathToImport != null) { - importFile(mFilePathToImport); - mFilePathToImport = null; - } } private void initScriptListRecyclerView() { @@ -103,9 +108,14 @@ public class MyScriptListFragment extends Fragment { } } }); + mScriptListRecyclerView.setOnCurrentDirectoryChangeListener(new ScriptAndFolderListRecyclerView.OnCurrentDirectoryChangeListener() { + @Override + public void onChange(ScriptFile oldDir, ScriptFile newDir) { + sCurrentDirectory = newDir; + } + }); } - private void initDialogs() { mScriptFileOperationDialog = new OperationDialogBuilder(getContext()) .item(R.id.loop, R.drawable.ic_loop_white_24dp, R.string.text_run_repeatedly) @@ -122,107 +132,11 @@ public class MyScriptListFragment extends Fragment { .build(); } - public void newScriptFileForScript(final String script) { - showFileNameInputDialog("", new MaterialDialog.InputCallback() { - @Override - public void onInput(@NonNull MaterialDialog dialog, CharSequence input) { - createScriptFile(getCurrentDirectoryPath() + input + ".js", script); - } - }); + + public static ScriptFile getCurrentDirectory() { + return sCurrentDirectory; } - private String getCurrentDirectoryPath() { - return getCurrentDirectory().getPath() + "/"; - } - - public void createScriptFile(String path, String script) { - if (PFile.createIfNotExists(path)) { - if (script != null) { - try { - PFile.write(path, script); - } catch (UncheckedIOException e) { - Snackbar.make(getView(), R.string.text_file_write_fail, Snackbar.LENGTH_LONG).show(); - } - } - notifyScriptFileChanged(); - Scripts.edit(path); - } else { - Snackbar.make(getView(), R.string.text_create_fail, Snackbar.LENGTH_LONG).show(); - } - } - - public void newScriptFile() { - newScriptFileForScript(null); - } - - public void importFile(final String pathFrom) { - if (getActivity() == null) { - mFilePathToImport = pathFrom; - return; - } - try { - importFile(PFile.getNameWithoutExtension(pathFrom), new FileInputStream(pathFrom)); - } catch (FileNotFoundException e) { - showMessage(R.string.file_not_exists); - } - } - - public void importFile(String prefix, final InputStream inputStream) { - showFileNameInputDialog(PFile.getNameWithoutExtension(prefix), new MaterialDialog.InputCallback() { - @Override - public void onInput(@NonNull MaterialDialog dialog, CharSequence input) { - final String pathTo = getCurrentDirectoryPath() + input + ".js"; - new Thread(new Runnable() { - @Override - public void run() { - if (PFile.copyStream(inputStream, pathTo)) { - showMessage(R.string.text_import_succeed); - } else { - showMessage(R.string.text_import_fail); - } - notifyScriptFileChanged(); - } - }).start(); - } - }); - } - - - public void newDirectory() { - showNameInputDialog("", new InputCallback(true), new MaterialDialog.InputCallback() { - @Override - public void onInput(@NonNull MaterialDialog dialog, CharSequence input) { - if (new ScriptFile(getCurrentDirectory(), input.toString()).mkdirs()) { - showMessage(R.string.text_already_create); - notifyScriptFileChanged(); - } else { - showMessage(R.string.text_create_fail); - } - } - }); - } - - private ScriptFile getCurrentDirectory() { - return mScriptListRecyclerView.getCurrentDirectory(); - } - - private void showFileNameInputDialog(String prefix, final MaterialDialog.InputCallback callback) { - showNameInputDialog(prefix, new InputCallback(false), callback); - } - - private void showNameInputDialog(String prefix, MaterialDialog.InputCallback textWatcher, final MaterialDialog.InputCallback callback) { - new ThemeColorMaterialDialogBuilder(getActivity()).title(R.string.text_name) - .inputType(InputType.TYPE_CLASS_TEXT) - .alwaysCallInputCallback() - .input(getString(R.string.text_please_input_name), prefix, false, textWatcher) - .onPositive(new MaterialDialog.SingleButtonCallback() { - @Override - public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) { - callback.onInput(dialog, dialog.getInputEditText().getText()); - } - }) - .show(); - } private void notifyScriptFileChanged() { getActivity().runOnUiThread(new Runnable() { @@ -245,15 +159,15 @@ public class MyScriptListFragment extends Fragment { @OnClick(R.id.rename) void renameScriptFile() { dismissDialogs(); - String originalName = mSelectedScriptFile.getSimplifiedName(); - showNameInputDialog(originalName, new InputCallback(mSelectedScriptFile.isDirectory(), originalName), new MaterialDialog.InputCallback() { - @Override - public void onInput(@NonNull MaterialDialog dialog, CharSequence input) { - mSelectedScriptFile.renameTo(input.toString()); - StorageScriptProvider.getDefault().notifyDirectoryChanged(mScriptListRecyclerView.getCurrentDirectory()); - onScriptFileOperated(); - } - }); + new ScriptOperations(getActivity(), getView()) + .rename(mSelectedScriptFile) + .subscribe(new Consumer() { + @Override + public void accept(@io.reactivex.annotations.NonNull Boolean renamed) throws Exception { + StorageScriptProvider.getDefault().notifyDirectoryChanged(mScriptListRecyclerView.getCurrentDirectory()); + onScriptFileOperated(); + } + }); } private void dismissDialogs() { @@ -274,7 +188,7 @@ public class MyScriptListFragment extends Fragment { private void onScriptFileOperated() { mSelectedScriptFile = null; - getView().post(new Runnable() { + getActivity().runOnUiThread(new Runnable() { @Override public void run() { mScriptListWithProgressBarView.hideProgressBar(); @@ -310,18 +224,21 @@ public class MyScriptListFragment extends Fragment { private void doDeletingScriptFile() { mScriptListWithProgressBarView.showProgressBar(); - UnderuseExecutors.execute(new Runnable() { + Observable.fromPublisher(new Publisher() { @Override - public void run() { - if (PFile.deleteRecursively(mSelectedScriptFile)) { - showMessage(R.string.text_already_delete); - notifyScriptFileChanged(); - } else { - showMessage(R.string.text_already_delete); - } - onScriptFileOperated(); + public void subscribe(Subscriber s) { + s.onNext(PFile.deleteRecursively(mSelectedScriptFile)); } - }); + }).subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Consumer() { + @Override + public void accept(@io.reactivex.annotations.NonNull Boolean deleted) throws Exception { + showMessage(deleted ? R.string.text_already_delete : R.string.text_delete_failed); + notifyScriptFileChanged(); + onScriptFileOperated(); + } + }); } private void showMessage(final int resId) { diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/main/script_list/ScriptAndFolderListRecyclerView.java b/app/src/main/java/com/stardust/scriptdroid/ui/main/script_list/ScriptAndFolderListRecyclerView.java index d7260f9d..6e8525c0 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/main/script_list/ScriptAndFolderListRecyclerView.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/main/script_list/ScriptAndFolderListRecyclerView.java @@ -27,10 +27,19 @@ import com.yqritc.recyclerviewflexibledivider.HorizontalDividerItemDecoration; import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; +import org.reactivestreams.Publisher; +import org.reactivestreams.Subscriber; import java.util.concurrent.Executor; import java.util.concurrent.Executors; +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.annotations.NonNull; +import io.reactivex.functions.Consumer; +import io.reactivex.schedulers.Schedulers; + /** * Created by Stardust on 2017/3/27. */ @@ -54,6 +63,12 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView { void onFileListed(); } + public interface OnCurrentDirectoryChangeListener { + + void onChange(ScriptFile oldDir, ScriptFile newDir); + + } + public static final int VIEW_TYPE_DIRECTORY = 1; public static final int VIEW_TYPE_FILE = 2; @@ -143,8 +158,8 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView { private boolean mCanGoBack = false; private StorageScriptProvider mStorageScriptProvider; private FileProcessListener mFileProcessListener; + private OnCurrentDirectoryChangeListener mOnCurrentDirectoryChangeListener; private boolean mScriptFileOperationEnabled = true; - private Executor mFileListingExecutor = Executors.newSingleThreadExecutor(); public ScriptAndFolderListRecyclerView(Context context) { super(context); @@ -162,26 +177,31 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView { } private void setCurrentDirectory(final ScriptFile directory, boolean canGoBack) { + if (!directory.equals(mCurrentDirectory) && mOnCurrentDirectoryChangeListener != null) { + mOnCurrentDirectoryChangeListener.onChange(mCurrentDirectory, directory); + } mCurrentDirectory = directory; mCanGoBack = canGoBack; if (mFileProcessListener != null) { mFileProcessListener.onFilesListing(); } - mFileListingExecutor.execute(new Runnable() { + Observable.fromPublisher(new Publisher() { @Override - public void run() { - final ScriptFile[] scriptFiles = mStorageScriptProvider.getDirectoryScriptFiles(directory); - post(new Runnable() { + public void subscribe(Subscriber s) { + s.onNext(mStorageScriptProvider.getDirectoryScriptFiles(directory)); + s.onComplete(); + } + }).subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Consumer() { @Override - public void run() { + public void accept(@NonNull ScriptFile[] scriptFiles) throws Exception { mAdapter.setScripts(scriptFiles); if (mFileProcessListener != null) mFileProcessListener.onFileListed(); smoothScrollToPosition(0); } }); - } - }); } public void setCurrentDirectory(final ScriptFile directory) { @@ -216,6 +236,10 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView { mOnItemLongClickListener = onItemLongClickListener; } + public void setOnCurrentDirectoryChangeListener(OnCurrentDirectoryChangeListener onCurrentDirectoryChangeListener) { + mOnCurrentDirectoryChangeListener = onCurrentDirectoryChangeListener; + } + public ScriptFile getCurrentDirectory() { return mCurrentDirectory; } @@ -297,7 +321,7 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView { return false; } - @Subscribe + @Subscribe(threadMode = ThreadMode.MAIN) public void onDirectoryChange(StorageScriptProvider.DirectoryChangeEvent event) { if (event.directory.equals(mCurrentDirectory)) { updateCurrentDirectory(); diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/main/task/TaskManagerFragment.java b/app/src/main/java/com/stardust/scriptdroid/ui/main/task/TaskManagerFragment.java index d73b9392..45b1fdfc 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/main/task/TaskManagerFragment.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/main/task/TaskManagerFragment.java @@ -45,6 +45,8 @@ public class TaskManagerFragment extends Fragment { mTaskListRecyclerView.postDelayed(new Runnable() { @Override public void run() { + if (mNoRunningScriptNotice == null) + return; mNoRunningScriptNotice.setVisibility(noRunningScript ? View.VISIBLE : View.GONE); mCloseAllView.setVisibility(noRunningScript ? View.GONE : View.VISIBLE); } diff --git a/app/src/main/res/drawable/ic_edit_white_24dp.png b/app/src/main/res/drawable/ic_edit_white_24dp.png new file mode 100644 index 00000000..02e19d04 Binary files /dev/null and b/app/src/main/res/drawable/ic_edit_white_24dp.png differ diff --git a/app/src/main/res/layout/activity_view_sample.xml b/app/src/main/res/layout/activity_view_sample.xml index 612c8ac7..8711d4ed 100644 --- a/app/src/main/res/layout/activity_view_sample.xml +++ b/app/src/main/res/layout/activity_view_sample.xml @@ -27,6 +27,14 @@ android:layout_gravity="right" android:orientation="horizontal"> + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 191ae18b..1925ef59 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -211,6 +211,7 @@ 没有相应,要强制停止吗 使用root权限开启失败 处理中 + 删除失败 diff --git a/common/src/main/java/com/stardust/pio/PFile.java b/common/src/main/java/com/stardust/pio/PFile.java index af85b005..670a9af1 100644 --- a/common/src/main/java/com/stardust/pio/PFile.java +++ b/common/src/main/java/com/stardust/pio/PFile.java @@ -142,7 +142,7 @@ public class PFile { return false; FileOutputStream fos = new FileOutputStream(file); write(is, fos); - return false; + return true; } catch (IOException | UncheckedIOException e) { e.printStackTrace(); return false;