From 544078892207f5800bc3c6ca8b0d6859d918ddd7 Mon Sep 17 00:00:00 2001 From: hyb1996 <946994919@qq.com> Date: Sun, 20 Aug 2017 21:46:51 +0800 Subject: [PATCH] new ui for script list --- .../content/ScriptListNavigatorContent.java | 20 +- .../external/tasker/TaskPrefEditActivity.java | 16 +- .../widget/ScriptWidgetSettingsActivity.java | 25 +- .../stardust/scriptdroid/script/Scripts.java | 10 +- ...Provider.java => StorageFileProvider.java} | 83 ++--- .../sublime/SublimeResponseHandler.java | 4 +- .../com/stardust/scriptdroid/tool/Logcat.java | 6 +- .../scriptdroid/tool/SimpleObserver.java | 32 ++ .../ui/common/ScriptOperations.java | 10 +- .../scriptdroid/ui/main/MainActivity.java | 23 +- .../script_list/MyScriptListFragment.java | 330 ++++++++++-------- .../ScriptFileChooserDialogBuilder.java | 16 +- ...rView.java => ScriptListRecyclerView.java} | 57 ++- .../ScriptListWithProgressBarView.java | 19 +- .../ui/update/UpdateInfoDialogBuilder.java | 4 +- .../java/com/stardust/widget/AutoAdapter.java | 63 ++++ .../stardust/widget/ViewHolderSupplier.java | 19 + app/src/main/res/drawable/circle_green.xml | 11 + .../main/res/drawable/ic_ascending_order.png | Bin 0 -> 628 bytes .../main/res/drawable/ic_descending_order.png | Bin 0 -> 639 bytes app/src/main/res/drawable/ic_sort.png | Bin 0 -> 505 bytes app/src/main/res/layout/activity_main.xml | 3 +- .../res/layout/fragment_my_script_list.xml | 29 +- .../layout/script_and_folder_list_view.xml | 2 +- .../res/layout/script_file_list_category.xml | 56 +++ .../res/layout/script_file_list_directory.xml | 59 ++++ .../main/res/layout/script_file_list_file.xml | 119 +++++++ app/src/main/res/layout/script_list_view.xml | 64 ++++ app/src/main/res/values/strings.xml | 2 + .../src/main/java/com/stardust/io/EFile.java | 29 ++ .../src/main/java/com/stardust/pio/PFile.java | 9 + 31 files changed, 783 insertions(+), 337 deletions(-) rename app/src/main/java/com/stardust/scriptdroid/script/{StorageScriptProvider.java => StorageFileProvider.java} (59%) create mode 100644 app/src/main/java/com/stardust/scriptdroid/tool/SimpleObserver.java rename app/src/main/java/com/stardust/scriptdroid/ui/main/script_list/{ScriptAndFolderListRecyclerView.java => ScriptListRecyclerView.java} (87%) create mode 100644 app/src/main/java/com/stardust/widget/AutoAdapter.java create mode 100644 app/src/main/res/drawable/circle_green.xml create mode 100644 app/src/main/res/drawable/ic_ascending_order.png create mode 100644 app/src/main/res/drawable/ic_descending_order.png create mode 100644 app/src/main/res/drawable/ic_sort.png create mode 100644 app/src/main/res/layout/script_file_list_category.xml create mode 100644 app/src/main/res/layout/script_file_list_directory.xml create mode 100644 app/src/main/res/layout/script_file_list_file.xml create mode 100644 app/src/main/res/layout/script_list_view.xml create mode 100644 common/src/main/java/com/stardust/io/EFile.java diff --git a/app/src/main/java/com/stardust/scriptdroid/external/floatingwindow/menu/content/ScriptListNavigatorContent.java b/app/src/main/java/com/stardust/scriptdroid/external/floatingwindow/menu/content/ScriptListNavigatorContent.java index 079f94cb..5293e63d 100644 --- a/app/src/main/java/com/stardust/scriptdroid/external/floatingwindow/menu/content/ScriptListNavigatorContent.java +++ b/app/src/main/java/com/stardust/scriptdroid/external/floatingwindow/menu/content/ScriptListNavigatorContent.java @@ -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 mViewHolderSupplier = new ViewHolderSupplier() { + private ViewHolderSupplier mViewHolderSupplier = new ViewHolderSupplier() { @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); diff --git a/app/src/main/java/com/stardust/scriptdroid/external/tasker/TaskPrefEditActivity.java b/app/src/main/java/com/stardust/scriptdroid/external/tasker/TaskPrefEditActivity.java index c8fb4a17..97ce7db9 100644 --- a/app/src/main/java/com/stardust/scriptdroid/external/tasker/TaskPrefEditActivity.java +++ b/app/src/main/java/com/stardust/scriptdroid/external/tasker/TaskPrefEditActivity.java @@ -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 { diff --git a/app/src/main/java/com/stardust/scriptdroid/external/widget/ScriptWidgetSettingsActivity.java b/app/src/main/java/com/stardust/scriptdroid/external/widget/ScriptWidgetSettingsActivity.java index 70e35f42..d82eb7d3 100644 --- a/app/src/main/java/com/stardust/scriptdroid/external/widget/ScriptWidgetSettingsActivity.java +++ b/app/src/main/java/com/stardust/scriptdroid/external/widget/ScriptWidgetSettingsActivity.java @@ -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; } diff --git a/app/src/main/java/com/stardust/scriptdroid/script/Scripts.java b/app/src/main/java/com/stardust/scriptdroid/script/Scripts.java index a8d34664..8f25630c 100644 --- a/app/src/main/java/com/stardust/scriptdroid/script/Scripts.java +++ b/app/src/main/java/com/stardust/scriptdroid/script/Scripts.java @@ -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)); } } diff --git a/app/src/main/java/com/stardust/scriptdroid/script/StorageScriptProvider.java b/app/src/main/java/com/stardust/scriptdroid/script/StorageFileProvider.java similarity index 59% rename from app/src/main/java/com/stardust/scriptdroid/script/StorageScriptProvider.java rename to app/src/main/java/com/stardust/scriptdroid/script/StorageFileProvider.java index 90a0bae5..4b861374 100644 --- a/app/src/main/java/com/stardust/scriptdroid/script/StorageScriptProvider.java +++ b/app/src/main/java/com/stardust/scriptdroid/script/StorageFileProvider.java @@ -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 getInitialDirectoryScriptFiles() { + return getDirectoryScriptFiles(mInitialDirectory); } - private ScriptFile[] getInitialDirectoryScriptFilesInner() { - return listAndSortFiles(mInitialDirectory); - } - - public ScriptFile[] getDirectoryScriptFiles(ScriptFile directory) { - if (directory.equals(mInitialDirectory)) { - return getInitialDirectoryScriptFiles(); - } + public Observable 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 listAndSortFiles(ScriptFile directory) { + return Observable.just(directory) + .observeOn(Schedulers.computation()) + .flatMap(new Function>() { - 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 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) { diff --git a/app/src/main/java/com/stardust/scriptdroid/sublime/SublimeResponseHandler.java b/app/src/main/java/com/stardust/scriptdroid/sublime/SublimeResponseHandler.java index 6d514df2..54dbfd2d 100644 --- a/app/src/main/java/com/stardust/scriptdroid/sublime/SublimeResponseHandler.java +++ b/app/src/main/java/com/stardust/scriptdroid/sublime/SublimeResponseHandler.java @@ -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 = "" + 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); } } diff --git a/app/src/main/java/com/stardust/scriptdroid/tool/Logcat.java b/app/src/main/java/com/stardust/scriptdroid/tool/Logcat.java index 5c22bca5..e34f4902 100644 --- a/app/src/main/java/com/stardust/scriptdroid/tool/Logcat.java +++ b/app/src/main/java/com/stardust/scriptdroid/tool/Logcat.java @@ -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() { diff --git a/app/src/main/java/com/stardust/scriptdroid/tool/SimpleObserver.java b/app/src/main/java/com/stardust/scriptdroid/tool/SimpleObserver.java new file mode 100644 index 00000000..0107bd82 --- /dev/null +++ b/app/src/main/java/com/stardust/scriptdroid/tool/SimpleObserver.java @@ -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 implements Observer { + @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() { + + } +} 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 index a47c5246..6c7349b7 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/common/ScriptOperations.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/common/ScriptOperations.java @@ -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) { 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 e3d47ff7..839862f4 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 @@ -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 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 301093c4..90ac0a29 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 @@ -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 mScriptFiles = new ArrayList<>(); + private ArrayList 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() { + + + @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() { - @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() { @Override public void subscribe(Subscriber s) { @@ -255,55 +225,123 @@ public class MyScriptListFragment extends Fragment { }); } + private class ScriptListAdapter extends RecyclerView.Adapter { - @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 { + + 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 { + + @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 { + + @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); + } + } + + } diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/main/script_list/ScriptFileChooserDialogBuilder.java b/app/src/main/java/com/stardust/scriptdroid/ui/main/script_list/ScriptFileChooserDialogBuilder.java index 5fb06c60..3f6e8375 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/main/script_list/ScriptFileChooserDialogBuilder.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/main/script_list/ScriptFileChooserDialogBuilder.java @@ -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); 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/ScriptListRecyclerView.java similarity index 87% rename from app/src/main/java/com/stardust/scriptdroid/ui/main/script_list/ScriptAndFolderListRecyclerView.java rename to app/src/main/java/com/stardust/scriptdroid/ui/main/script_list/ScriptListRecyclerView.java index ee66c75d..9d421fb7 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/ScriptListRecyclerView.java @@ -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() { - @Override - public void subscribe(Subscriber s) { - s.onNext(mStorageScriptProvider.getDirectoryScriptFiles(directory)); - s.onComplete(); - } - }).subscribeOn(Schedulers.io()) + mStorageFileProvider.getDirectoryScriptFiles(directory) + .subscribeOn(Schedulers.io()) + .toList() .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new Consumer() { + .subscribe(new Consumer>() { @Override - public void accept(@NonNull ScriptFile[] scriptFiles) throws Exception { - mAdapter.setScripts(scriptFiles); + public void accept(@NonNull List 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(); } diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/main/script_list/ScriptListWithProgressBarView.java b/app/src/main/java/com/stardust/scriptdroid/ui/main/script_list/ScriptListWithProgressBarView.java index a35c4352..be77bc11 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/main/script_list/ScriptListWithProgressBarView.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/main/script_list/ScriptListWithProgressBarView.java @@ -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); } diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/update/UpdateInfoDialogBuilder.java b/app/src/main/java/com/stardust/scriptdroid/ui/update/UpdateInfoDialogBuilder.java index d6049f1f..712e6bb6 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/update/UpdateInfoDialogBuilder.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/update/UpdateInfoDialogBuilder.java @@ -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) { diff --git a/app/src/main/java/com/stardust/widget/AutoAdapter.java b/app/src/main/java/com/stardust/widget/AutoAdapter.java new file mode 100644 index 00000000..e3453724 --- /dev/null +++ b/app/src/main/java/com/stardust/widget/AutoAdapter.java @@ -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
extends RecyclerView.Adapter> { + + private ViewHolderSupplier> mViewHolderSupplier; + private List
mList = new ArrayList<>(); + + public AutoAdapter(ViewHolderSupplier> viewHolderSupplier) { + mViewHolderSupplier = viewHolderSupplier; + } + + + @Override + public BindableViewHolder
onCreateViewHolder(ViewGroup parent, int viewType) { + return mViewHolderSupplier.createViewHolder(parent, viewType); + } + + @Override + public void onBindViewHolder(BindableViewHolder
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 c) { + mList.addAll(c); + notifyItemRangeInserted(mList.size() - c.size() - 1, mList.size() - 1); + } + + public void setData(Collection c) { + mList.clear(); + mList.addAll(c); + notifyDataSetChanged(); + } + +} diff --git a/app/src/main/java/com/stardust/widget/ViewHolderSupplier.java b/app/src/main/java/com/stardust/widget/ViewHolderSupplier.java index 2d67c760..7df88c06 100644 --- a/app/src/main/java/com/stardust/widget/ViewHolderSupplier.java +++ b/app/src/main/java/com/stardust/widget/ViewHolderSupplier.java @@ -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 { public abstract VH createViewHolder(ViewGroup parent, int viewType); + public static ViewHolderSupplier of(final Class c, final int layoutRes) { + return new ViewHolderSupplier() { + @Override + public VH createViewHolder(ViewGroup parent, int viewType) { + try { + Constructor constructor = c.getConstructor(View.class); + return constructor.newInstance(LayoutInflater.from(parent.getContext()).inflate(layoutRes, parent, false)); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }; + } + } diff --git a/app/src/main/res/drawable/circle_green.xml b/app/src/main/res/drawable/circle_green.xml new file mode 100644 index 00000000..95376eb4 --- /dev/null +++ b/app/src/main/res/drawable/circle_green.xml @@ -0,0 +1,11 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_ascending_order.png b/app/src/main/res/drawable/ic_ascending_order.png new file mode 100644 index 0000000000000000000000000000000000000000..350043d80c5c9341441a59ec4060dc474463135e GIT binary patch literal 628 zcmV-)0*n2LP)Z2U>x4psx<*2t>w5?La%w4uA^O3bX`$b-b)|Dh^_j+XN=w zjmK*?$^U2f%LYJb_y-%VAO4>KH5zrZ0=jwLyAH{o)_R8k$02j9u|(56mpiku;0z4) z*_epBWQt9t)H7F5Ees5YqeDQtDn%2}pf9Cri~*%o2Q%@Ah@F{eQ;1EaPM$a>{yYN% ztuGPqXhG~Gm#4e6H}Cf6~7g_eKdcFG~h)Zw*;G6vU zO^D!$%-ePd&{ZNs#w%~3d2n3|hXNfUuqxJTzy_{s!4ROUM1_od4Ggqa2-s&X=mq+V zqYLI*Kf-($h0}mi=Np+Q9z!EJay)dss$7b2uiDSTx0eV@{ z^Ybe^aT)9_tA#HZs}#psE17|^JcTd^98myf>Z|)d$w0_06!Nx8mVwrQqxRYi0P_|q zAx80b$bmQmnA8qpj_{b6WF-_Mjx(n+u)0eD-S_8FiWKAfc&;J$7rR^XI;l3~BaR|K0A&wEpnUf4+j+mI3)A5d4h!N`Vq*4byn%NkxCKwKR`|UD O0000TZ_6STQO`r3)4j%dQz zu4S!ckCP0_lP6xS_V@0$E1STc|Hz)l4<|-e*8e zr+uo;ZHy32$@hHS=Y4cmLQUoX0rQ1(KC2R+1Yj9R8Q69SH5p_|sksnhxm5;Yx({Ye zXAon8iLprnuw6)qn;v8O0{4{ltE=yq*LRkIkTz<-OvaoGjMyXqTS6%Vj(X~>ge=5_ ztu8TjO#x;*2Qen_7@I-{uCL_`2sw>$RIz4}@lmfOUrsj#0XEH)sh@3ZT6czT!@u*T zzV<5|a%W@Ud7O>T^5%7e%otc?+3*4BzF_tr#P-xk*@69RaTMba0Df!5`a)d&%CE0& zqYd7xE4z@C^2`8vj1l0PqMZt`fky)E1h;bmF+dYA=bZDWs?2pRzy=Wnw5N{WKC38w zS0&C6n2$OC7E`jdlQ;xut=MrH+?aqu*LaT-7@$Lrzo7y8?7adIKrggf^<6LBz5tru zM+v9{x(?jpAQOj_emdFwr}dv7ZHPt*SOa}WfP5`Hv48kpSsk4KUSl4e*WZ1q#MCn)jEyqc6HEjJ zmBEGXg8vGjCQQMjotVXPDG@Msnfwnn0WD(A<*qAQc1{`;0HQY`_(WHL1?ojt%Rxc! zr3$9q73ljJs2G%KI$?^YgcOn*Wxe_fIk12e$YD1!CzM$R9j*dW%8;?qBLQ6^Vh99T zS#EEolpD(=8o{+Hut-*GM3`xvIFETW*LSS09f-SK+bFAs;1a2bqbS!u9n^`5XcG&5 zS_f&mGucl57mx5-i2JN-CvLh*d?vlM3@4= z2?6A!wl}>w#Lj$d8F;vTz%o(J;D)V$AL^YM=MUHq^?s=DZZkjB`=P$OTe`0tb|dS~ v!|_&n1&+u4_s(7cuYe%~-a>{18i#)ZbpGZsHrP>200000NkvXXu0mjf+v3~p literal 0 HcmV?d00001 diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 94f58a15..570571f0 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -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"/> - + - - - - - \ No newline at end of file + android:layout_height="wrap_content"/> + \ No newline at end of file diff --git a/app/src/main/res/layout/script_and_folder_list_view.xml b/app/src/main/res/layout/script_and_folder_list_view.xml index 97bd4802..358eb56d 100644 --- a/app/src/main/res/layout/script_and_folder_list_view.xml +++ b/app/src/main/res/layout/script_and_folder_list_view.xml @@ -8,7 +8,7 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - diff --git a/app/src/main/res/layout/script_file_list_category.xml b/app/src/main/res/layout/script_file_list_category.xml new file mode 100644 index 00000000..40412703 --- /dev/null +++ b/app/src/main/res/layout/script_file_list_category.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/script_file_list_directory.xml b/app/src/main/res/layout/script_file_list_directory.xml new file mode 100644 index 00000000..1ad796a3 --- /dev/null +++ b/app/src/main/res/layout/script_file_list_directory.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/script_file_list_file.xml b/app/src/main/res/layout/script_file_list_file.xml new file mode 100644 index 00000000..fd79d22e --- /dev/null +++ b/app/src/main/res/layout/script_file_list_file.xml @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/script_list_view.xml b/app/src/main/res/layout/script_list_view.xml new file mode 100644 index 00000000..5d59d364 --- /dev/null +++ b/app/src/main/res/layout/script_list_view.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 86be9313..5bf53b6a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -227,6 +227,8 @@ key_enable_observe_key 不启动则无法使用events的按键事件; 启用后软件崩溃等情况会造成按键失灵。重启无障碍服务生效 启用按键监听 + 文件夹 + 文件 diff --git a/common/src/main/java/com/stardust/io/EFile.java b/common/src/main/java/com/stardust/io/EFile.java new file mode 100644 index 00000000..8331bcf2 --- /dev/null +++ b/common/src/main/java/com/stardust/io/EFile.java @@ -0,0 +1,29 @@ +package com.stardust.io; + +import android.support.annotation.NonNull; + +import java.io.File; +import java.net.URI; + +/** + * Created by Stardust on 2017/8/19. + */ + +public class EFile extends File { + + public EFile(@NonNull String pathname) { + super(pathname); + } + + public EFile(String parent, @NonNull String child) { + super(parent, child); + } + + public EFile(File parent, @NonNull String child) { + super(parent, child); + } + + public EFile(@NonNull URI uri) { + super(uri); + } +} diff --git a/common/src/main/java/com/stardust/pio/PFile.java b/common/src/main/java/com/stardust/pio/PFile.java index 670a9af1..733908aa 100644 --- a/common/src/main/java/com/stardust/pio/PFile.java +++ b/common/src/main/java/com/stardust/pio/PFile.java @@ -16,6 +16,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.charset.Charset; +import java.util.Locale; /** * Created by Stardust on 2017/4/1. @@ -346,4 +347,12 @@ public class PFile { public static String join(String parent, String child) { return new File(parent, child).getPath(); } + + public static String getHumanReadableSize(long bytes) { + int unit = 1024; + if (bytes < unit) return bytes + " B"; + int exp = (int) (Math.log(bytes) / Math.log(unit)); + String pre = "KMGTPE".substring(exp - 1, exp); + return String.format(Locale.getDefault(), "%.1f %sB", bytes / Math.pow(unit, exp), pre); + } }