new ui for script list

This commit is contained in:
hyb1996
2017-08-20 21:46:51 +08:00
parent 68de90b718
commit 5440788922
31 changed files with 783 additions and 337 deletions

View File

@@ -15,10 +15,10 @@ import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.external.floatingwindow.menu.HoverMenuService;
import com.stardust.scriptdroid.script.ScriptFile;
import com.stardust.scriptdroid.script.Scripts;
import com.stardust.scriptdroid.script.StorageScriptProvider;
import com.stardust.scriptdroid.script.StorageFileProvider;
import com.stardust.scriptdroid.ui.common.ScriptLoopDialog;
import com.stardust.scriptdroid.ui.edit.EditActivity;
import com.stardust.scriptdroid.ui.main.script_list.ScriptAndFolderListRecyclerView;
import com.stardust.scriptdroid.ui.main.script_list.ScriptListRecyclerView;
import com.stardust.scriptdroid.ui.main.script_list.ScriptListWithProgressBarView;
import com.stardust.widget.ViewHolderSupplier;
@@ -31,20 +31,20 @@ import io.mattcarroll.hover.NavigatorContent;
public class ScriptListNavigatorContent implements NavigatorContent {
private ViewHolderSupplier<ScriptAndFolderListRecyclerView.ViewHolder> mViewHolderSupplier = new ViewHolderSupplier<ScriptAndFolderListRecyclerView.ViewHolder>() {
private ViewHolderSupplier<ScriptListRecyclerView.ViewHolder> mViewHolderSupplier = new ViewHolderSupplier<ScriptListRecyclerView.ViewHolder>() {
@Override
public ScriptAndFolderListRecyclerView.ViewHolder createViewHolder(ViewGroup parent, int viewType) {
public ScriptListRecyclerView.ViewHolder createViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case ScriptAndFolderListRecyclerView.VIEW_TYPE_FILE:
case ScriptListRecyclerView.VIEW_TYPE_FILE:
return new FileViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.floating_script_list_recycler_view_file, parent, false));
case ScriptAndFolderListRecyclerView.VIEW_TYPE_DIRECTORY:
case ScriptListRecyclerView.VIEW_TYPE_DIRECTORY:
return new DirectoryViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.floating_script_list_recycler_view_directory, parent, false));
}
return null;
}
};
private ScriptAndFolderListRecyclerView mFloatingScriptFileListView;
private ScriptListRecyclerView mFloatingScriptFileListView;
private ScriptListWithProgressBarView mScriptListWithProgressBarView;
public ScriptListNavigatorContent(Context context) {
@@ -52,8 +52,8 @@ public class ScriptListNavigatorContent implements NavigatorContent {
mFloatingScriptFileListView = mScriptListWithProgressBarView.getScriptAndFolderListRecyclerView();
mFloatingScriptFileListView.setViewHolderSupplier(mViewHolderSupplier);
mFloatingScriptFileListView.setLayoutManager(new WrapContentLinearLayoutManager(context));
mFloatingScriptFileListView.setStorageScriptProvider(StorageScriptProvider.getDefault());
mFloatingScriptFileListView.setOnItemClickListener(new ScriptAndFolderListRecyclerView.OnScriptFileClickListener() {
mFloatingScriptFileListView.setStorageFileProvider(StorageFileProvider.getDefault());
mFloatingScriptFileListView.setOnItemClickListener(new ScriptListRecyclerView.OnScriptFileClickListener() {
@Override
public void onClick(ScriptFile file, int position) {
@@ -80,7 +80,7 @@ public class ScriptListNavigatorContent implements NavigatorContent {
}
private class DirectoryViewHolder extends ScriptAndFolderListRecyclerView.ViewHolder {
private class DirectoryViewHolder extends ScriptListRecyclerView.ViewHolder {
DirectoryViewHolder(View itemView) {
super(itemView);

View File

@@ -11,9 +11,9 @@ import android.view.MenuItem;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.external.CommonUtils;
import com.stardust.scriptdroid.script.ScriptFile;
import com.stardust.scriptdroid.script.StorageScriptProvider;
import com.stardust.scriptdroid.script.StorageFileProvider;
import com.stardust.scriptdroid.ui.BaseActivity;
import com.stardust.scriptdroid.ui.main.script_list.ScriptAndFolderListRecyclerView;
import com.stardust.scriptdroid.ui.main.script_list.ScriptListRecyclerView;
import com.stardust.scriptdroid.ui.main.script_list.ScriptListWithProgressBarView;
import com.twofortyfouram.locale.sdk.client.ui.activity.AbstractAppCompatPluginActivity;
@@ -29,7 +29,7 @@ public class TaskPrefEditActivity extends AbstractAppCompatPluginActivity {
private String mSelectedScriptFilePath;
private String mPreExecuteScript;
private StorageScriptProvider mStorageScriptProvider;
private StorageFileProvider mStorageFileProvider;
@AfterViews
void setUpViews() {
@@ -39,12 +39,12 @@ public class TaskPrefEditActivity extends AbstractAppCompatPluginActivity {
private void initScriptListRecyclerView() {
mStorageScriptProvider = StorageScriptProvider.getExternalStorageProvider();
mStorageFileProvider = StorageFileProvider.getExternalStorageProvider();
ScriptListWithProgressBarView scriptList = (ScriptListWithProgressBarView) findViewById(R.id.script_list);
scriptList.setScriptFileOperationEnabled(false);
scriptList.setStorageScriptProvider(mStorageScriptProvider);
scriptList.setCurrentDirectory(StorageScriptProvider.DEFAULT_DIRECTORY);
scriptList.setOnItemClickListener(new ScriptAndFolderListRecyclerView.OnScriptFileClickListener() {
scriptList.setStorageScriptProvider(mStorageFileProvider);
scriptList.setCurrentDirectory(StorageFileProvider.DEFAULT_DIRECTORY);
scriptList.setOnItemClickListener(new ScriptListRecyclerView.OnScriptFileClickListener() {
@Override
public void onClick(ScriptFile file, int position) {
mSelectedScriptFilePath = file.getPath();
@@ -62,7 +62,7 @@ public class TaskPrefEditActivity extends AbstractAppCompatPluginActivity {
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.action_refresh) {
mStorageScriptProvider.refreshAll();
mStorageFileProvider.refreshAll();
} else if (item.getItemId() == R.id.action_clear_file_selection) {
mSelectedScriptFilePath = null;
} else {

View File

@@ -1,29 +1,20 @@
package com.stardust.scriptdroid.external.widget;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.RemoteViews;
import android.widget.Toast;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.external.CommonUtils;
import com.stardust.scriptdroid.external.open.RunIntentActivity;
import com.stardust.scriptdroid.external.tasker.TaskerScriptEditActivity;
import com.stardust.scriptdroid.script.ScriptFile;
import com.stardust.scriptdroid.script.StorageScriptProvider;
import com.stardust.scriptdroid.script.StorageFileProvider;
import com.stardust.scriptdroid.ui.BaseActivity;
import com.stardust.scriptdroid.ui.main.script_list.ScriptAndFolderListRecyclerView;
import com.stardust.scriptdroid.ui.main.script_list.ScriptListRecyclerView;
import com.stardust.scriptdroid.ui.main.script_list.ScriptListWithProgressBarView;
import org.androidannotations.annotations.AfterViews;
import org.androidannotations.annotations.Click;
import org.androidannotations.annotations.EActivity;
/**
@@ -34,7 +25,7 @@ public class ScriptWidgetSettingsActivity extends BaseActivity {
private String mSelectedScriptFilePath;
private StorageScriptProvider mStorageScriptProvider;
private StorageFileProvider mStorageFileProvider;
private int mAppWidgetId;
@Override
@@ -51,12 +42,12 @@ public class ScriptWidgetSettingsActivity extends BaseActivity {
private void initScriptListRecyclerView() {
mStorageScriptProvider = StorageScriptProvider.getExternalStorageProvider();
mStorageFileProvider = StorageFileProvider.getExternalStorageProvider();
ScriptListWithProgressBarView scriptList = (ScriptListWithProgressBarView) findViewById(R.id.script_list);
scriptList.setScriptFileOperationEnabled(false);
scriptList.setStorageScriptProvider(mStorageScriptProvider);
scriptList.setCurrentDirectory(StorageScriptProvider.DEFAULT_DIRECTORY);
scriptList.setOnItemClickListener(new ScriptAndFolderListRecyclerView.OnScriptFileClickListener() {
scriptList.setStorageScriptProvider(mStorageFileProvider);
scriptList.setCurrentDirectory(StorageFileProvider.DEFAULT_DIRECTORY);
scriptList.setOnItemClickListener(new ScriptListRecyclerView.OnScriptFileClickListener() {
@Override
public void onClick(ScriptFile file, int position) {
mSelectedScriptFilePath = file.getPath();
@@ -69,7 +60,7 @@ public class ScriptWidgetSettingsActivity extends BaseActivity {
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.action_refresh) {
mStorageScriptProvider.refreshAll();
mStorageFileProvider.refreshAll();
} else if (item.getItemId() == R.id.action_clear_file_selection) {
mSelectedScriptFilePath = null;
}

View File

@@ -84,17 +84,17 @@ public class Scripts {
public static ScriptExecution run(ScriptSource source, String directoryPath) {
return AutoJs.getInstance().getScriptEngineService().execute(source, new ExecutionConfig()
.path(directoryPath, StorageScriptProvider.DEFAULT_DIRECTORY_PATH));
.path(directoryPath, StorageFileProvider.DEFAULT_DIRECTORY_PATH));
}
public static ScriptExecution run(ScriptSource source) {
return AutoJs.getInstance().getScriptEngineService().execute(source, new ExecutionConfig()
.path(StorageScriptProvider.DEFAULT_DIRECTORY_PATH));
.path(StorageFileProvider.DEFAULT_DIRECTORY_PATH));
}
public static ScriptExecution runWithBroadcastSender(ScriptSource scriptSource, String directoryPath) {
return AutoJs.getInstance().getScriptEngineService().execute(scriptSource, BROADCAST_SENDER_SCRIPT_EXECUTION_LISTENER,
new ExecutionConfig().path(directoryPath, StorageScriptProvider.DEFAULT_DIRECTORY_PATH));
new ExecutionConfig().path(directoryPath, StorageFileProvider.DEFAULT_DIRECTORY_PATH));
}
public static ScriptExecution run(Context context, Sample file) {
@@ -104,14 +104,14 @@ public class Scripts {
public static ScriptExecution runWithBroadcastSender(ScriptSource source) {
return AutoJs.getInstance().getScriptEngineService().execute(source, BROADCAST_SENDER_SCRIPT_EXECUTION_LISTENER,
new ExecutionConfig().path(StorageScriptProvider.DEFAULT_DIRECTORY_PATH));
new ExecutionConfig().path(StorageFileProvider.DEFAULT_DIRECTORY_PATH));
}
public static ScriptExecution runRepeatedly(ScriptFile scriptFile, int loopTimes, long delay, long interval) {
ScriptSource source = scriptFile.toSource();
String directoryPath = scriptFile.getParent();
return AutoJs.getInstance().getScriptEngineService().execute(source, new ExecutionConfig()
.path(directoryPath, StorageScriptProvider.DEFAULT_DIRECTORY_PATH)
.path(directoryPath, StorageFileProvider.DEFAULT_DIRECTORY_PATH)
.loop(delay, loopTimes, interval));
}
}

View File

@@ -11,11 +11,17 @@ import org.greenrobot.eventbus.EventBus;
import java.util.Map;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
/**
* Created by Stardust on 2017/3/31.
*/
public class StorageScriptProvider {
public class StorageFileProvider {
public static class DirectoryChangeEvent {
@@ -31,17 +37,17 @@ public class StorageScriptProvider {
public static final ScriptFile DEFAULT_DIRECTORY = new ScriptFile(DEFAULT_DIRECTORY_PATH);
private static StorageScriptProvider defaultProvider = new StorageScriptProvider();
private static StorageFileProvider defaultProvider = new StorageFileProvider();
public static StorageScriptProvider getDefault() {
public static StorageFileProvider getDefault() {
return defaultProvider;
}
private static StorageScriptProvider externalStorageProvider;
private static StorageFileProvider externalStorageProvider;
public static StorageScriptProvider getExternalStorageProvider() {
public static StorageFileProvider getExternalStorageProvider() {
if (externalStorageProvider == null) {
externalStorageProvider = new StorageScriptProvider(Environment.getExternalStorageDirectory().getPath(), 5);
externalStorageProvider = new StorageFileProvider(Environment.getExternalStorageDirectory().getPath(), 5);
}
return externalStorageProvider;
}
@@ -51,25 +57,21 @@ public class StorageScriptProvider {
private ScriptFile mInitialDirectory;
private ScriptFile[] mInitialDirectoryScriptFiles;
public StorageScriptProvider(String path, int cacheSize) {
public StorageFileProvider(String path, int cacheSize) {
this(new ScriptFile(path), cacheSize);
}
public StorageScriptProvider(ScriptFile initialDirectory, int cacheSize) {
public StorageFileProvider(ScriptFile initialDirectory, int cacheSize) {
mInitialDirectory = initialDirectory;
mScriptFileCache = new LimitedHashMap<>(cacheSize);
}
public StorageScriptProvider() {
public StorageFileProvider() {
this(DEFAULT_DIRECTORY, 10);
}
public void notifyDirectoryChanged(ScriptFile directory) {
if (directory.equals(mInitialDirectory)) {
mInitialDirectoryScriptFiles = getInitialDirectoryScriptFilesInner();
} else {
clearCache(directory);
}
clearCache(directory);
mDirectoryEventBus.post(new DirectoryChangeEvent(directory));
}
@@ -94,30 +96,16 @@ public class StorageScriptProvider {
return mInitialDirectory;
}
public ScriptFile[] getInitialDirectoryScriptFiles() {
if (mInitialDirectoryScriptFiles == null) {
mInitialDirectoryScriptFiles = getInitialDirectoryScriptFilesInner();
}
return mInitialDirectoryScriptFiles;
public Observable<ScriptFile> getInitialDirectoryScriptFiles() {
return getDirectoryScriptFiles(mInitialDirectory);
}
private ScriptFile[] getInitialDirectoryScriptFilesInner() {
return listAndSortFiles(mInitialDirectory);
}
public ScriptFile[] getDirectoryScriptFiles(ScriptFile directory) {
if (directory.equals(mInitialDirectory)) {
return getInitialDirectoryScriptFiles();
}
public Observable<ScriptFile> getDirectoryScriptFiles(ScriptFile directory) {
ScriptFile[] scriptFiles = getScriptFilesFromCache(directory);
if (scriptFiles == null) {
scriptFiles = getScriptFiles(directory);
return listAndSortFiles(directory);
}
return scriptFiles;
}
public void clearCacheExceptInitialDirectory() {
mScriptFileCache.clear();
return Observable.fromArray(scriptFiles);
}
private void clearCache(ScriptFile directory) {
@@ -125,19 +113,24 @@ public class StorageScriptProvider {
}
private ScriptFile[] getScriptFiles(ScriptFile directory) {
ScriptFile[] scriptFiles = listAndSortFiles(directory);
mScriptFileCache.put(directory.getPath(), scriptFiles);
return scriptFiles;
}
private Observable<ScriptFile> listAndSortFiles(ScriptFile directory) {
return Observable.just(directory)
.observeOn(Schedulers.computation())
.flatMap(new Function<ScriptFile, Observable<ScriptFile>>() {
private ScriptFile[] listAndSortFiles(ScriptFile directory) {
ScriptFile[] scriptFiles = directory.listFiles();
if (scriptFiles == null)
scriptFiles = new ScriptFile[0];
else
FileSorter.sort(scriptFiles);
return scriptFiles;
@Override
public Observable<ScriptFile> apply(@NonNull ScriptFile dir) throws Exception {
ScriptFile[] scriptFiles = dir.listFiles();
if (scriptFiles == null) {
return Observable.empty();
} else {
FileSorter.sort(scriptFiles);
mScriptFileCache.put(dir.getPath(), scriptFiles);
return Observable.fromArray(scriptFiles);
}
}
});
}
private ScriptFile[] getScriptFilesFromCache(ScriptFile directory) {

View File

@@ -13,7 +13,7 @@ import com.stardust.scriptdroid.App;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.autojs.AutoJs;
import com.stardust.scriptdroid.script.Scripts;
import com.stardust.scriptdroid.script.StorageScriptProvider;
import com.stardust.scriptdroid.script.StorageFileProvider;
/**
* Created by Stardust on 2017/5/11.
@@ -114,7 +114,7 @@ public class SublimeResponseHandler implements Handler {
} else {
name = "<remote>" + name;
}
PFile.write(StorageScriptProvider.DEFAULT_DIRECTORY_PATH + name, script);
PFile.write(StorageFileProvider.DEFAULT_DIRECTORY_PATH + name, script);
App.getApp().getUiHandler().toast(R.string.text_script_save_successfully);
}
}

View File

@@ -1,6 +1,6 @@
package com.stardust.scriptdroid.tool;
import com.stardust.scriptdroid.script.StorageScriptProvider;
import com.stardust.scriptdroid.script.StorageFileProvider;
import java.io.File;
import java.io.IOException;
@@ -11,8 +11,8 @@ import java.io.IOException;
public class Logcat {
private static final String LOG_PATH = StorageScriptProvider.DEFAULT_DIRECTORY_PATH + "log.txt";
private static final String DISABLE_PATH = StorageScriptProvider.DEFAULT_DIRECTORY_PATH + "disable_log.txt";
private static final String LOG_PATH = StorageFileProvider.DEFAULT_DIRECTORY_PATH + "log.txt";
private static final String DISABLE_PATH = StorageFileProvider.DEFAULT_DIRECTORY_PATH + "disable_log.txt";
private static Process sLogSavingProcess;
public static void startLogSavingIfNeeded() {

View File

@@ -0,0 +1,32 @@
package com.stardust.scriptdroid.tool;
import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.annotations.NonNull;
import io.reactivex.disposables.Disposable;
/**
* Created by Stardust on 2017/8/20.
*/
public class SimpleObserver<T> implements Observer<T> {
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull T t) {
}
@Override
public void onError(@NonNull Throwable e) {
}
@Override
public void onComplete() {
}
}

View File

@@ -1,31 +1,25 @@
package com.stardust.scriptdroid.ui.common;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.ContextWrapper;
import android.os.Looper;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.text.InputType;
import android.view.View;
import android.view.WindowManager;
import android.widget.EditText;
import android.widget.Toast;
import com.afollestad.materialdialogs.DialogAction;
import com.afollestad.materialdialogs.MaterialDialog;
import com.jecelyin.common.utils.L;
import com.stardust.app.DialogUtils;
import com.stardust.autojs.runtime.api.ui.Dialogs;
import com.stardust.pio.PFile;
import com.stardust.pio.UncheckedIOException;
import com.stardust.scriptdroid.App;
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.StorageFileProvider;
import com.stardust.scriptdroid.script.sample.Sample;
import com.stardust.scriptdroid.ui.main.script_list.MyScriptListFragment;
import com.stardust.theme.dialog.ThemeColorMaterialDialogBuilder;
@@ -158,7 +152,7 @@ public class ScriptOperations {
}
private void notifyScriptFileChanged() {
StorageScriptProvider.getDefault().notifyDirectoryChanged(mCurrentDirectory);
StorageFileProvider.getDefault().notifyDirectoryChanged(mCurrentDirectory);
}
private void showMessage(final int resId) {

View File

@@ -3,24 +3,18 @@ package com.stardust.scriptdroid.ui.main;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.afollestad.materialdialogs.DialogAction;
import com.afollestad.materialdialogs.MaterialDialog;
@@ -36,12 +30,11 @@ import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.autojs.AutoJs;
import com.stardust.scriptdroid.external.floatingwindow.HoverMenuManger;
import com.stardust.scriptdroid.script.ScriptFile;
import com.stardust.scriptdroid.script.StorageScriptProvider;
import com.stardust.scriptdroid.script.StorageFileProvider;
import com.stardust.scriptdroid.ui.common.ScriptOperations;
import com.stardust.scriptdroid.ui.main.script_list.MyScriptListFragment_;
import com.stardust.scriptdroid.ui.main.task.TaskManagerFragment_;
import com.stardust.util.DeveloperUtils;
import com.stardust.util.IntentExtras;
import com.stardust.view.accessibility.AccessibilityService;
import com.stardust.scriptdroid.tool.AccessibilityServiceTool;
import com.stardust.scriptdroid.tool.DrawableSaver;
import com.stardust.scriptdroid.ui.BaseActivity;
@@ -50,11 +43,9 @@ import com.stardust.scriptdroid.ui.main.script_list.MyScriptListFragment;
import com.stardust.scriptdroid.ui.main.script_list.ScriptFileChooserDialogBuilder;
import com.stardust.scriptdroid.ui.settings.SettingsActivity_;
import com.stardust.scriptdroid.ui.update.VersionGuard;
import com.stardust.theme.dialog.ThemeColorMaterialDialogBuilder;
import com.stardust.util.BackPressedHandler;
import com.stardust.util.MessageEvent;
import com.stardust.view.DrawerAutoClose;
import com.stardust.view.accessibility.AccessibilityServiceUtils;
import com.stardust.widget.CommonMarkdownView;
import com.stardust.widget.SlidingUpPanel;
@@ -65,8 +56,6 @@ import org.androidannotations.annotations.ViewById;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import java.io.InputStream;
@EActivity(R.layout.activity_main)
public class MainActivity extends BaseActivity implements OnActivityResultDelegate.DelegateHost {
@@ -195,7 +184,7 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega
private void setUpTabViewPager() {
TabLayout tabLayout = $(R.id.tab);
mPagerAdapter = new FragmentPagerAdapterBuilder(this)
.add(new MyScriptListFragment(), R.string.text_my_script)
.add(new MyScriptListFragment_(), R.string.text_my_script)
.add(new SampleScriptListFragment(), R.string.text_sample_script)
.add(new TaskManagerFragment_(), R.string.text_task_manage)
.build();
@@ -222,14 +211,14 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega
@Click(R.id.import_from_file)
void showFileChooser() {
final StorageScriptProvider provider = StorageScriptProvider.getExternalStorageProvider();
final StorageFileProvider provider = StorageFileProvider.getExternalStorageProvider();
new ScriptFileChooserDialogBuilder(this)
.scriptProvider(provider)
.fileCallback(new ScriptFileChooserDialogBuilder.FileCallback() {
@Override
public void onFileSelection(MaterialDialog dialog, final ScriptFile file) {
dialog.dismiss();
provider.clearCacheExceptInitialDirectory();
provider.refreshAll();
new ScriptOperations(MainActivity.this, mDrawerLayout)
.importFile(file.getPath())
.subscribe();
@@ -303,7 +292,7 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
StorageScriptProvider.getDefault().notifyStoragePermissionGranted();
StorageFileProvider.getDefault().notifyStoragePermissionGranted();
}
@Override

View File

@@ -1,140 +1,132 @@
package com.stardust.scriptdroid.ui.main.script_list;
import android.content.DialogInterface;
import android.os.Bundle;
import android.graphics.drawable.GradientDrawable;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.text.InputType;
import android.support.v4.app.Fragment;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.TextView;
import com.afollestad.materialdialogs.DialogAction;
import com.afollestad.materialdialogs.MaterialDialog;
import com.stardust.app.Fragment;
import com.stardust.app.OperationDialogBuilder;
import com.stardust.pio.UncheckedIOException;
import com.stardust.scriptdroid.script.ScriptFile;
import com.stardust.pio.PFile;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.script.Scripts;
import com.stardust.scriptdroid.script.StorageScriptProvider;
import com.stardust.scriptdroid.script.StorageFileProvider;
import com.stardust.scriptdroid.tool.SimpleObserver;
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 com.stardust.widget.AutoAdapter;
import com.stardust.widget.BindableViewHolder;
import com.stardust.widget.ViewHolderSupplier;
import com.yqritc.recyclerviewflexibledivider.HorizontalDividerItemDecoration;
import org.androidannotations.annotations.AfterViews;
import org.androidannotations.annotations.EFragment;
import org.androidannotations.annotations.ViewById;
import org.reactivestreams.Publisher;
import org.reactivestreams.Subscriber;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.concurrent.Callable;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.Optional;
import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Predicate;
import io.reactivex.schedulers.Schedulers;
/**
* Created by Stardust on 2017/3/13.
*/
@EFragment(R.layout.fragment_my_script_list)
public class MyScriptListFragment extends Fragment {
public static final String MESSAGE_SCRIPT_FILE_ADDED = "MESSAGE_SCRIPT_FILE_ADDED";
private static final String TAG = "MyScriptListFragment";
private static ScriptFile sCurrentDirectory = StorageScriptProvider.DEFAULT_DIRECTORY;
private static ScriptFile sCurrentDirectory = StorageFileProvider.DEFAULT_DIRECTORY;
private ScriptAndFolderListRecyclerView mScriptListRecyclerView;
private ScriptListWithProgressBarView mScriptListWithProgressBarView;
private View mNoScriptHint;
private MaterialDialog mScriptFileOperationDialog;
private MaterialDialog mDirectoryOperationDialog;
@ViewById(R.id.script_file_list)
RecyclerView mScriptFileList;
@ViewById(R.id.swipe_refresh_layout)
SwipeRefreshLayout mSwipeRefreshLayout;
private ScriptListAdapter mScriptListAdapter = new ScriptListAdapter();
private ScriptFile mSelectedScriptFile;
@Nullable
@Override
public View createView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_my_script_list, container, false);
}
private ArrayList<ScriptFile> mScriptFiles = new ArrayList<>();
private ArrayList<ScriptFile> mDirectories = new ArrayList<>();
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mScriptListWithProgressBarView = $(R.id.script_list);
mScriptListRecyclerView = mScriptListWithProgressBarView.getScriptAndFolderListRecyclerView();
mNoScriptHint = $(R.id.hint_no_script);
@AfterViews
void setUpViews() {
initScriptListRecyclerView();
initDialogs();
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
loadScriptList();
}
});
}
private void initScriptListRecyclerView() {
mScriptListWithProgressBarView.setStorageScriptProvider(StorageScriptProvider.getDefault());
mScriptListRecyclerView.getAdapter().registerAdapterDataObserver(new SimpleAdapterDataObserver() {
mScriptFileList.setAdapter(mScriptListAdapter);
GridLayoutManager manager = new GridLayoutManager(getContext(), 2);
manager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public void onSomethingChanged() {
if (mScriptListRecyclerView.getAdapter().getItemCount() == 0) {
mNoScriptHint.setVisibility(View.VISIBLE);
} else {
mNoScriptHint.setVisibility(View.GONE);
public int getSpanSize(int position) {
//For directories
if (position >= 1 && position <= mDirectories.size()) {
return 1;
}
//For files and category
return 2;
}
});
mScriptListRecyclerView.setOnItemClickListener(new ScriptAndFolderListRecyclerView.OnScriptFileClickListener() {
@Override
public void onClick(ScriptFile file, int position) {
if (file.getType() == ScriptFile.TYPE_JAVA_SCRIPT) {
Scripts.edit(file);
} else {
mSelectedScriptFile = file;
mScriptFileOperationDialog.show();
}
}
});
mScriptListRecyclerView.setOnItemLongClickListener(new ScriptAndFolderListRecyclerView.OnScriptFileLongClickListener() {
@Override
public void onLongClick(ScriptFile file, int position) {
mSelectedScriptFile = file;
if (file.isDirectory()) {
mDirectoryOperationDialog.show();
} else {
mScriptFileOperationDialog.show();
}
}
});
mScriptListRecyclerView.setOnCurrentDirectoryChangeListener(new ScriptAndFolderListRecyclerView.OnCurrentDirectoryChangeListener() {
@Override
public void onChange(ScriptFile oldDir, ScriptFile newDir) {
sCurrentDirectory = newDir;
}
});
mScriptFileList.setLayoutManager(manager);
loadScriptList();
}
private void initDialogs() {
mScriptFileOperationDialog = new OperationDialogBuilder(getContext())
.item(R.id.loop, R.drawable.ic_loop_white_24dp, R.string.text_run_repeatedly)
.item(R.id.rename, R.drawable.ic_ali_rename, R.string.text_rename)
.item(R.id.open_by_other_apps, R.drawable.ic_ali_open, R.string.text_open_by_other_apps)
.item(R.id.create_shortcut, R.drawable.ic_ali_shortcut, R.string.text_send_shortcut)
.item(R.id.delete, R.drawable.ic_ali_delete, R.string.text_delete)
.bindItemClick(this)
.build();
mDirectoryOperationDialog = new OperationDialogBuilder(getContext())
.item(R.id.rename, R.drawable.ic_ali_rename, R.string.text_rename)
.item(R.id.delete, R.drawable.ic_ali_delete, R.string.text_delete)
.bindItemClick(this)
.build();
private void loadScriptList() {
mScriptFiles.clear();
mDirectories.clear();
StorageFileProvider.getDefault().getInitialDirectoryScriptFiles()
.subscribeOn(Schedulers.computation())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new SimpleObserver<ScriptFile>() {
@Override
public void onNext(@io.reactivex.annotations.NonNull ScriptFile file) {
if (file.isFile()) {
mScriptFiles.add(file);
} else {
mDirectories.add(file);
}
}
@Override
public void onComplete() {
mScriptListAdapter.notifyDataSetChanged();
mSwipeRefreshLayout.setRefreshing(false);
}
});
}
@@ -147,7 +139,7 @@ public class MyScriptListFragment extends Fragment {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
StorageScriptProvider.getDefault().notifyDirectoryChanged(getCurrentDirectory());
StorageFileProvider.getDefault().notifyDirectoryChanged(getCurrentDirectory());
}
});
}
@@ -155,7 +147,6 @@ public class MyScriptListFragment extends Fragment {
@Optional
@OnClick(R.id.loop)
void runScriptRepeatedly() {
dismissDialogs();
new ScriptLoopDialog(getActivity(), mSelectedScriptFile)
.show();
}
@@ -163,30 +154,12 @@ public class MyScriptListFragment extends Fragment {
@Optional
@OnClick(R.id.rename)
void renameScriptFile() {
dismissDialogs();
new ScriptOperations(getActivity(), getView())
.rename(mSelectedScriptFile)
.subscribe(new Consumer<Boolean>() {
@Override
public void accept(@io.reactivex.annotations.NonNull Boolean renamed) throws Exception {
StorageScriptProvider.getDefault().notifyDirectoryChanged(mScriptListRecyclerView.getCurrentDirectory());
onScriptFileOperated();
}
});
}
private void dismissDialogs() {
if (mDirectoryOperationDialog.isShowing())
mDirectoryOperationDialog.dismiss();
if (mScriptFileOperationDialog.isShowing())
mScriptFileOperationDialog.dismiss();
}
@Optional
@OnClick(R.id.open_by_other_apps)
void openByOtherApps() {
dismissDialogs();
Scripts.openByOtherApps(mSelectedScriptFile);
onScriptFileOperated();
}
@@ -196,7 +169,7 @@ public class MyScriptListFragment extends Fragment {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
mScriptListWithProgressBarView.hideProgressBar();
mSwipeRefreshLayout.setRefreshing(false);
}
});
}
@@ -204,7 +177,6 @@ public class MyScriptListFragment extends Fragment {
@Optional
@OnClick(R.id.create_shortcut)
void createShortcut() {
dismissDialogs();
Scripts.createShortcut(mSelectedScriptFile);
Snackbar.make(getView(), R.string.text_already_create, Snackbar.LENGTH_SHORT).show();
onScriptFileOperated();
@@ -213,7 +185,6 @@ public class MyScriptListFragment extends Fragment {
@Optional
@OnClick(R.id.delete)
void deleteScriptFile() {
dismissDialogs();
new MaterialDialog.Builder(getActivity())
.title(R.string.delete_confirm)
.positiveText(R.string.cancel)
@@ -228,7 +199,6 @@ public class MyScriptListFragment extends Fragment {
}
private void doDeletingScriptFile() {
mScriptListWithProgressBarView.showProgressBar();
Observable.fromPublisher(new Publisher<Boolean>() {
@Override
public void subscribe(Subscriber<? super Boolean> s) {
@@ -255,55 +225,123 @@ public class MyScriptListFragment extends Fragment {
});
}
private class ScriptListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
@Override
public void onResume() {
super.onResume();
mScriptListRecyclerView.setFocusableInTouchMode(true);
mScriptListRecyclerView.requestFocus();
}
private final int VIEW_TYPE_FILE = 0;
private final int VIEW_TYPE_DIRECTORY = 1;
//category是类别也即"文件", "文件夹"那两个
private final int VIEW_TYPE_CATEGORY = 2;
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;
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
if (viewType == VIEW_TYPE_FILE) {
return new ScriptFileViewHolder(inflater.inflate(R.layout.script_file_list_file, parent, false));
} else if (viewType == VIEW_TYPE_DIRECTORY) {
return new DirectoryViewHolder(inflater.inflate(R.layout.script_file_list_directory, parent, false));
} else {
return new CategoryViewHolder(inflater.inflate(R.layout.script_file_list_category, parent, false));
}
}
InputCallback(boolean isDirectory) {
mIsDirectory = isDirectory;
@SuppressWarnings("unchecked")
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
BindableViewHolder bindableViewHolder = (BindableViewHolder) holder;
if (position == 0 || position == mDirectories.size() + 1) {
bindableViewHolder.bind(position == 0, position);
return;
}
if (position <= mDirectories.size()) {
bindableViewHolder.bind(mDirectories.get(position - 1), position);
return;
}
bindableViewHolder.bind(mScriptFiles.get(position - mDirectories.size() - 2), position);
}
@Override
public void onInput(@NonNull MaterialDialog dialog, CharSequence input) {
if (mIsFirstTextChanged) {
mIsFirstTextChanged = false;
return;
public int getItemViewType(int position) {
if (position == 0 || position == mDirectories.size() + 1) {
return VIEW_TYPE_CATEGORY;
}
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 (position <= mDirectories.size()) {
return VIEW_TYPE_DIRECTORY;
}
if (errorResId == 0) {
editText.setError(null);
dialog.getActionButton(DialogAction.POSITIVE).setEnabled(true);
return VIEW_TYPE_FILE;
}
@Override
public int getItemCount() {
return mScriptFiles.size() + mDirectories.size() + 2;
}
}
static class ScriptFileViewHolder extends BindableViewHolder<ScriptFile> {
private static final DateFormat DATE_FORMAT = SimpleDateFormat.getDateTimeInstance();
@BindView(R.id.name)
TextView mName;
@BindView(R.id.first_char)
TextView mFirstChar;
@BindView(R.id.desc)
TextView mDesc;
GradientDrawable mFirstCharBackground;
public ScriptFileViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
mFirstCharBackground = (GradientDrawable) mFirstChar.getBackground();
}
@Override
public void bind(ScriptFile file, int position) {
mName.setText(file.getSimplifiedName());
mDesc.setText(PFile.getHumanReadableSize(file.length()));
if (file.getType() == ScriptFile.TYPE_JAVA_SCRIPT) {
mFirstChar.setText("J");
//什么?裸写颜色代码?!不影响代码可读性和重构成本的情况下,这样子修改起来方便多啦
mFirstCharBackground.setColor(0xFF99CC99);
} else {
editText.setError(getString(errorResId));
dialog.getActionButton(DialogAction.POSITIVE).setEnabled(false);
mFirstChar.setText("R");
mFirstCharBackground.setColor(0xFFFD999A);
}
}
}
static class DirectoryViewHolder extends BindableViewHolder<ScriptFile> {
@BindView(R.id.name)
TextView mName;
public DirectoryViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
@Override
public void bind(ScriptFile data, int position) {
mName.setText(data.getSimplifiedName());
}
}
static class CategoryViewHolder extends BindableViewHolder<Boolean> {
@BindView(R.id.title)
TextView mTitle;
public CategoryViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
@Override
public void bind(Boolean isDirCategory, int position) {
mTitle.setText(isDirCategory ? R.string.text_directory : R.string.text_file);
}
}
}

View File

@@ -5,7 +5,7 @@ import android.support.annotation.NonNull;
import com.afollestad.materialdialogs.MaterialDialog;
import com.stardust.scriptdroid.script.ScriptFile;
import com.stardust.scriptdroid.script.StorageScriptProvider;
import com.stardust.scriptdroid.script.StorageFileProvider;
/**
* Created by Stardust on 2017/4/3.
@@ -18,7 +18,7 @@ public class ScriptFileChooserDialogBuilder extends MaterialDialog.Builder {
}
private ScriptListWithProgressBarView mScriptListWithProgressBarView;
private StorageScriptProvider mStorageScriptProvider;
private StorageFileProvider mStorageFileProvider;
private FileCallback mFileCallback;
public ScriptFileChooserDialogBuilder(@NonNull Context context) {
@@ -34,23 +34,23 @@ public class ScriptFileChooserDialogBuilder extends MaterialDialog.Builder {
}
public ScriptFileChooserDialogBuilder initialPath(String initialPath) {
mStorageScriptProvider = new StorageScriptProvider(initialPath, 5);
mStorageFileProvider = new StorageFileProvider(initialPath, 5);
return this;
}
public ScriptFileChooserDialogBuilder scriptProvider(StorageScriptProvider storageScriptProvider) {
mStorageScriptProvider = storageScriptProvider;
public ScriptFileChooserDialogBuilder scriptProvider(StorageFileProvider storageFileProvider) {
mStorageFileProvider = storageFileProvider;
return this;
}
public MaterialDialog build() {
if (mStorageScriptProvider != null) {
mScriptListWithProgressBarView.setStorageScriptProvider(mStorageScriptProvider);
if (mStorageFileProvider != null) {
mScriptListWithProgressBarView.setStorageScriptProvider(mStorageFileProvider);
}
customView(mScriptListWithProgressBarView, false);
final MaterialDialog dialog = super.build();
if (mFileCallback != null) {
mScriptListWithProgressBarView.setOnItemClickListener(new ScriptAndFolderListRecyclerView.OnScriptFileClickListener() {
mScriptListWithProgressBarView.setOnItemClickListener(new ScriptListRecyclerView.OnScriptFileClickListener() {
@Override
public void onClick(ScriptFile file, int position) {
mFileCallback.onFileSelection(dialog, file);

View File

@@ -4,7 +4,6 @@ import android.content.Context;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.annotation.Nullable;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.KeyEvent;
@@ -19,8 +18,7 @@ import android.workground.WrapContentLinearLayoutManager;
import com.stardust.scriptdroid.script.ScriptFile;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.script.Scripts;
import com.stardust.scriptdroid.script.StorageScriptProvider;
import com.stardust.util.ViewUtil;
import com.stardust.scriptdroid.script.StorageFileProvider;
import com.stardust.util.ViewUtils;
import com.stardust.widget.ViewHolderMutableAdapter;
import com.stardust.widget.ViewHolderSupplier;
@@ -32,8 +30,7 @@ import org.greenrobot.eventbus.ThreadMode;
import org.reactivestreams.Publisher;
import org.reactivestreams.Subscriber;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.List;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
@@ -45,7 +42,7 @@ import io.reactivex.schedulers.Schedulers;
* Created by Stardust on 2017/3/27.
*/
public class ScriptAndFolderListRecyclerView extends RecyclerView {
public class ScriptListRecyclerView extends RecyclerView {
public interface OnScriptFileClickListener {
@@ -157,22 +154,22 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView {
private ScriptFile mRootDirectory;
private Adapter mAdapter;
private boolean mCanGoBack = false;
private StorageScriptProvider mStorageScriptProvider;
private StorageFileProvider mStorageFileProvider;
private FileProcessListener mFileProcessListener;
private OnCurrentDirectoryChangeListener mOnCurrentDirectoryChangeListener;
private boolean mScriptFileOperationEnabled = true;
public ScriptAndFolderListRecyclerView(Context context) {
public ScriptListRecyclerView(Context context) {
super(context);
init();
}
public ScriptAndFolderListRecyclerView(Context context, @Nullable AttributeSet attrs) {
public ScriptListRecyclerView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public ScriptAndFolderListRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
public ScriptListRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
@@ -186,18 +183,14 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView {
if (mFileProcessListener != null) {
mFileProcessListener.onFilesListing();
}
Observable.fromPublisher(new Publisher<ScriptFile[]>() {
@Override
public void subscribe(Subscriber<? super ScriptFile[]> s) {
s.onNext(mStorageScriptProvider.getDirectoryScriptFiles(directory));
s.onComplete();
}
}).subscribeOn(Schedulers.io())
mStorageFileProvider.getDirectoryScriptFiles(directory)
.subscribeOn(Schedulers.io())
.toList()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<ScriptFile[]>() {
.subscribe(new Consumer<List<ScriptFile>>() {
@Override
public void accept(@NonNull ScriptFile[] scriptFiles) throws Exception {
mAdapter.setScripts(scriptFiles);
public void accept(@NonNull List<ScriptFile> scriptFiles) throws Exception {
mAdapter.setScripts(scriptFiles.toArray(new ScriptFile[0]));
if (mFileProcessListener != null)
mFileProcessListener.onFileListed();
smoothScrollToPosition(0);
@@ -217,16 +210,16 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView {
mFileProcessListener = fileProcessListener;
}
public void setStorageScriptProvider(StorageScriptProvider storageScriptProvider) {
if (mStorageScriptProvider != null)
mStorageScriptProvider.unregisterDirectoryChangeListener(this);
mStorageScriptProvider = storageScriptProvider;
mStorageScriptProvider.registerDirectoryChangeListener(this);
setRootDirectory(mStorageScriptProvider.getInitialDirectory());
public void setStorageFileProvider(StorageFileProvider storageFileProvider) {
if (mStorageFileProvider != null)
mStorageFileProvider.unregisterDirectoryChangeListener(this);
mStorageFileProvider = storageFileProvider;
mStorageFileProvider.registerDirectoryChangeListener(this);
setRootDirectory(mStorageFileProvider.getInitialDirectory());
}
public StorageScriptProvider getStorageScriptProvider() {
return mStorageScriptProvider;
public StorageFileProvider getStorageFileProvider() {
return mStorageFileProvider;
}
public void setOnItemClickListener(OnScriptFileClickListener onItemClickListener) {
@@ -300,15 +293,15 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView {
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (mStorageScriptProvider != null)
mStorageScriptProvider.registerDirectoryChangeListener(this);
if (mStorageFileProvider != null)
mStorageFileProvider.registerDirectoryChangeListener(this);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mStorageScriptProvider.unregisterDirectoryChangeListener(this);
mStorageFileProvider.unregisterDirectoryChangeListener(this);
}
@Override
@@ -323,7 +316,7 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView {
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onDirectoryChange(StorageScriptProvider.DirectoryChangeEvent event) {
public void onDirectoryChange(StorageFileProvider.DirectoryChangeEvent event) {
if (event.directory.equals(mCurrentDirectory)) {
updateCurrentDirectory();
}

View File

@@ -10,12 +10,11 @@ import android.support.annotation.RequiresApi;
import android.support.annotation.StyleRes;
import android.support.v4.widget.SwipeRefreshLayout;
import android.util.AttributeSet;
import android.view.View;
import android.widget.FrameLayout;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.script.ScriptFile;
import com.stardust.scriptdroid.script.StorageScriptProvider;
import com.stardust.scriptdroid.script.StorageFileProvider;
/**
* Created by Stardust on 2017/4/3.
@@ -23,7 +22,7 @@ import com.stardust.scriptdroid.script.StorageScriptProvider;
public class ScriptListWithProgressBarView extends FrameLayout {
private ScriptAndFolderListRecyclerView mScriptAndFolderListRecyclerView;
private ScriptListRecyclerView mScriptAndFolderListRecyclerView;
private SwipeRefreshLayout mSwipeRefreshLayout;
public ScriptListWithProgressBarView(@NonNull Context context) {
@@ -50,8 +49,8 @@ public class ScriptListWithProgressBarView extends FrameLayout {
private void init() {
inflate(getContext(), R.layout.script_and_folder_list_view, this);
mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh_layout);
mScriptAndFolderListRecyclerView = (ScriptAndFolderListRecyclerView) findViewById(R.id.script_list_recycler_view);
mScriptAndFolderListRecyclerView.setFileProcessListener(new ScriptAndFolderListRecyclerView.FileProcessListener() {
mScriptAndFolderListRecyclerView = (ScriptListRecyclerView) findViewById(R.id.script_list_recycler_view);
mScriptAndFolderListRecyclerView.setFileProcessListener(new ScriptListRecyclerView.FileProcessListener() {
@Override
public void onFilesListing() {
showProgressBar();
@@ -65,22 +64,22 @@ public class ScriptListWithProgressBarView extends FrameLayout {
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
mScriptAndFolderListRecyclerView.getStorageScriptProvider().refreshAll();
mScriptAndFolderListRecyclerView.getStorageFileProvider().refreshAll();
}
});
}
public ScriptAndFolderListRecyclerView getScriptAndFolderListRecyclerView() {
public ScriptListRecyclerView getScriptAndFolderListRecyclerView() {
return mScriptAndFolderListRecyclerView;
}
public void setStorageScriptProvider(StorageScriptProvider storageScriptProvider) {
mScriptAndFolderListRecyclerView.setStorageScriptProvider(storageScriptProvider);
public void setStorageScriptProvider(StorageFileProvider storageFileProvider) {
mScriptAndFolderListRecyclerView.setStorageFileProvider(storageFileProvider);
}
public void setOnItemClickListener(ScriptAndFolderListRecyclerView.OnScriptFileClickListener onItemClickListener) {
public void setOnItemClickListener(ScriptListRecyclerView.OnScriptFileClickListener onItemClickListener) {
mScriptAndFolderListRecyclerView.setOnItemClickListener(onItemClickListener);
}

View File

@@ -16,7 +16,7 @@ import android.widget.Toast;
import com.afollestad.materialdialogs.MaterialDialog;
import com.stardust.scriptdroid.BuildConfig;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.script.StorageScriptProvider;
import com.stardust.scriptdroid.script.StorageFileProvider;
import com.stardust.scriptdroid.tool.IntentTool;
import com.stardust.scriptdroid.tool.UpdateChecker;
import com.stardust.util.DownloadTask;
@@ -117,7 +117,7 @@ public class UpdateInfoDialogBuilder extends MaterialDialog.Builder {
.title(R.string.text_downloading)
.progress(false, 100)
.show();
final String path = StorageScriptProvider.DEFAULT_DIRECTORY_PATH + "AutoJs.apk";
final String path = StorageFileProvider.DEFAULT_DIRECTORY_PATH + "AutoJs.apk";
final DownloadTask task = new DownloadTask() {
@Override
protected void onProgressUpdate(Integer... values) {

View File

@@ -0,0 +1,63 @@
package com.stardust.widget;
import android.support.v7.widget.RecyclerView;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* Created by Stardust on 2017/8/19.
*/
public class AutoAdapter<DT> extends RecyclerView.Adapter<BindableViewHolder<DT>> {
private ViewHolderSupplier<? extends BindableViewHolder<DT>> mViewHolderSupplier;
private List<DT> mList = new ArrayList<>();
public AutoAdapter(ViewHolderSupplier<? extends BindableViewHolder<DT>> viewHolderSupplier) {
mViewHolderSupplier = viewHolderSupplier;
}
@Override
public BindableViewHolder<DT> onCreateViewHolder(ViewGroup parent, int viewType) {
return mViewHolderSupplier.createViewHolder(parent, viewType);
}
@Override
public void onBindViewHolder(BindableViewHolder<DT> holder, int position) {
holder.bind(mList.get(position), position);
}
@Override
public int getItemCount() {
return mList.size();
}
public void remove(DT data) {
int pos = mList.indexOf(data);
if (pos < 0)
return;
mList.remove(pos);
notifyItemRemoved(pos);
}
public void remove(int index) {
mList.remove(index);
notifyItemRemoved(index);
}
public void addAll(Collection<? extends DT> c) {
mList.addAll(c);
notifyItemRangeInserted(mList.size() - c.size() - 1, mList.size() - 1);
}
public void setData(Collection<? extends DT> c) {
mList.clear();
mList.addAll(c);
notifyDataSetChanged();
}
}

View File

@@ -1,8 +1,13 @@
package com.stardust.widget;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/**
* Created by Stardust on 2017/4/8.
*/
@@ -11,4 +16,18 @@ public abstract class ViewHolderSupplier<VH extends RecyclerView.ViewHolder> {
public abstract VH createViewHolder(ViewGroup parent, int viewType);
public static <VH extends RecyclerView.ViewHolder> ViewHolderSupplier<VH> of(final Class<VH> c, final int layoutRes) {
return new ViewHolderSupplier<VH>() {
@Override
public VH createViewHolder(ViewGroup parent, int viewType) {
try {
Constructor<VH> constructor = c.getConstructor(View.class);
return constructor.newInstance(LayoutInflater.from(parent.getContext()).inflate(layoutRes, parent, false));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
};
}
}

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="32dp"/>
<size
android:width="64dp"
android:height="64dp"/>
<solid android:color="#5cab7d"/>
</shape>

Binary file not shown.

After

Width:  |  Height:  |  Size: 628 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 639 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 505 B

View File

@@ -16,8 +16,7 @@
android:id="@+id/app_bar_bg"
android:layout_width="match_parent"
android:layout_height="128.5dp"
android:scaleType="fitXY"
android:src="@drawable/toolbar_bg"/>
android:scaleType="fitXY"/>
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"

View File

@@ -1,24 +1,11 @@
<?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:orientation="vertical">
<android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/swipe_refresh_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.stardust.scriptdroid.ui.main.script_list.ScriptListWithProgressBarView
android:id="@+id/script_list"
<android.support.v7.widget.RecyclerView
android:id="@+id/script_file_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#f2f3f5"/>
<TextView
android:id="@+id/hint_no_script"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:text="@string/hint_no_script"
android:textColor="#adadad"
android:textSize="16sp"
android:visibility="gone"/>
</FrameLayout>
android:layout_height="wrap_content"/>
</android.support.v4.widget.SwipeRefreshLayout>

View File

@@ -8,7 +8,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.stardust.scriptdroid.ui.main.script_list.ScriptAndFolderListRecyclerView
<com.stardust.scriptdroid.ui.main.script_list.ScriptListRecyclerView
android:id="@+id/script_list_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

View File

@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="?selectableItemBackground"
android:clickable="true"
android:orientation="horizontal"
android:paddingBottom="8dp"
android:paddingTop="8dp">
<ImageView
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_gravity="center_vertical"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:src="@drawable/ic_expanded"
android:tint="#828384"/>
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/text_directory"
android:textColor="#828384"
android:textSize="12sp"/>
</LinearLayout>
<ImageView
android:layout_width="32dp"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:background="?selectableItemBackgroundBorderless"
android:clickable="true"
android:padding="9dp"
android:src="@drawable/ic_descending_order"
android:tint="#828384"/>
<ImageView
android:layout_width="32dp"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:background="?selectableItemBackgroundBorderless"
android:clickable="true"
android:padding="9dp"
android:src="@drawable/ic_sort"
android:tint="#828384"/>
</LinearLayout>

View File

@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:foreground="?selectableItemBackground"
android:paddingLeft="6dp"
android:paddingRight="6dp"
app:cardBackgroundColor="#ffffff"
app:cardElevation="1dp"
app:cardUseCompatPadding="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:paddingBottom="16dp"
android:paddingTop="16dp">
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_vertical"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:src="@drawable/ic_folder_yellow_100px"
android:tint="#ffde69"/>
<TextView
android:id="@+id/name"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:ellipsize="end"
android:gravity="center_vertical"
android:maxLines="1"
android:paddingRight="16dp"
android:textColor="#484C4F"
android:textSize="14sp"
tools:text="正在运行的服务"/>
<ImageView
android:layout_width="52dp"
android:layout_height="20dp"
android:layout_gravity="center_vertical"
android:background="?selectableItemBackgroundBorderless"
android:clickable="true"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:src="@drawable/ic_more_vert_black_24dp"
android:tint="#A9AAAB"/>
</LinearLayout>
</android.support.v7.widget.CardView>

View File

@@ -0,0 +1,119 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:background="#EDEEEF"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/white"
android:clickable="true"
android:foreground="?selectableItemBackground"
android:orientation="horizontal"
android:padding="8dp">
<TextView
android:id="@+id/first_char"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center_vertical"
android:layout_marginLeft="8dp"
android:background="@drawable/circle_green"
android:gravity="center"
android:textColor="@android:color/white"
android:textSize="24sp"
tools:text="J"/>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="16dp"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:gravity="center_vertical"
android:maxLines="1"
android:textColor="#484C4F"
android:textSize="14sp"
tools:text="正在运行的服务"/>
<TextView
android:id="@+id/desc"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginTop="4dp"
android:ellipsize="end"
android:gravity="center_vertical"
android:maxLines="1"
android:text="2017年2月3日11:56"
android:textColor="#9DA0A2"
android:textSize="11sp"
tools:text="正在运行的服务"/>
</LinearLayout>
<LinearLayout
android:layout_width="108dp"
android:layout_height="34dp"
android:layout_gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:id="@+id/run"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="?selectableItemBackgroundBorderless"
android:clickable="true"
android:paddingBottom="8dp"
android:paddingTop="8dp"
android:src="@drawable/ic_run_gray"
android:tint="#A9AAAB"/>
<ImageView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="?selectableItemBackgroundBorderless"
android:clickable="true"
android:paddingBottom="8dp"
android:paddingTop="8dp"
android:src="@drawable/ic_mode_edit_black_24dp"
android:tint="#A9AAAB"/>
<ImageView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="?selectableItemBackgroundBorderless"
android:clickable="true"
android:paddingBottom="8dp"
android:paddingTop="8dp"
android:src="@drawable/ic_more_vert_black_24dp"
android:tint="#A9AAAB"/>
</LinearLayout>
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:background="#EDEEEF"/>
</LinearLayout>

View File

@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="8dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/text_directory"
android:textColor="#828384"
android:textSize="12sp"/>
</LinearLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/directory_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="6dp"
android:paddingRight="6dp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="8dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/text_file"
android:textColor="#828384"
android:textSize="12sp"/>
</LinearLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/script_file_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
</LinearLayout>
</ScrollView>

View File

@@ -227,6 +227,8 @@
<string name="key_enable_observe_key">key_enable_observe_key</string>
<string name="summary_enable_observe_key">不启动则无法使用events的按键事件; 启用后软件崩溃等情况会造成按键失灵。重启无障碍服务生效</string>
<string name="text_enable_observe_key">启用按键监听</string>
<string name="text_directory">文件夹</string>
<string name="text_file">文件</string>
<string-array name="record_control_keys">