From be022f1c941113e3d3fbb756b85e5695fd9df637 Mon Sep 17 00:00:00 2001 From: hyb1996 <946994919@qq.com> Date: Sat, 30 Sep 2017 19:12:07 +0800 Subject: [PATCH] add: file sorting --- app/build.gradle | 4 +- .../scriptdroid/script/ScriptFileList.java | 42 ------ .../script/SharedPrefScriptFileList.java | 103 -------------- .../script/StorageFileProvider.java | 2 +- .../scriptdroid/ui/edit/CodeMirrorEditor.java | 51 ++++--- .../scriptdroid/ui/floating/EditorFloaty.java | 105 ++++++++++++++ .../ui/main/scripts/MyScriptListFragment.java | 8 +- .../ui/main/scripts/ScriptListView.java | 133 ++++++++++++++---- .../scriptdroid/ui/viewmodel/ScriptList.java | 113 +++++++++++++++ .../java/com/stardust/widget/EWebView.java | 1 + app/src/main/res/layout/floating_editor.xml | 60 ++++++++ app/src/main/res/menu/menu_sort_options.xml | 8 +- app/src/main/res/values/strings.xml | 2 + .../stardust/scriptdroid/ExampleUnitTest.java | 33 ++++- .../java/com/stardust/util/FileSorter.java | 79 +++++++++-- 15 files changed, 532 insertions(+), 212 deletions(-) delete mode 100644 app/src/main/java/com/stardust/scriptdroid/script/ScriptFileList.java delete mode 100644 app/src/main/java/com/stardust/scriptdroid/script/SharedPrefScriptFileList.java create mode 100644 app/src/main/java/com/stardust/scriptdroid/ui/floating/EditorFloaty.java create mode 100644 app/src/main/java/com/stardust/scriptdroid/ui/viewmodel/ScriptList.java create mode 100644 app/src/main/res/layout/floating_editor.xml diff --git a/app/build.gradle b/app/build.gradle index ca0ee38f..c9c74d81 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -9,8 +9,8 @@ android { applicationId "com.stardust.scriptdroid" minSdkVersion 17 targetSdkVersion 23 - versionCode 205 - versionName "3.0.0 Alpha6" + versionCode 206 + versionName "3.0.0 Alpha7" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" multiDexEnabled true ndk { diff --git a/app/src/main/java/com/stardust/scriptdroid/script/ScriptFileList.java b/app/src/main/java/com/stardust/scriptdroid/script/ScriptFileList.java deleted file mode 100644 index 4d9ee899..00000000 --- a/app/src/main/java/com/stardust/scriptdroid/script/ScriptFileList.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.stardust.scriptdroid.script; - -import java.io.File; - -/** - * Created by Stardust on 2017/1/23. - */ - -public abstract class ScriptFileList { - - private static ScriptFileList impl; - - public static void setImpl(ScriptFileList list) { - impl = list; - } - - public static ScriptFileList getImpl() { - return impl; - } - - public abstract void add(ScriptFile scriptFile); - - public abstract ScriptFile get(int i); - - public abstract void remove(int i); - - public abstract void rename(int position, String newName, boolean renameFile); - - public abstract int size(); - - public boolean deleteFromFileSystem(int i) { - if (i < 0 || i >= size()) - return false; - File file = get(i); - remove(i); - return file.delete(); - } - - public abstract boolean containsPath(String path); - - -} diff --git a/app/src/main/java/com/stardust/scriptdroid/script/SharedPrefScriptFileList.java b/app/src/main/java/com/stardust/scriptdroid/script/SharedPrefScriptFileList.java deleted file mode 100644 index 7815ff57..00000000 --- a/app/src/main/java/com/stardust/scriptdroid/script/SharedPrefScriptFileList.java +++ /dev/null @@ -1,103 +0,0 @@ -package com.stardust.scriptdroid.script; - -import android.content.Context; -import android.content.SharedPreferences; - -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; -import com.stardust.pio.PFile; -import com.stardust.scriptdroid.App; - -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Stardust on 2017/1/23. - */ - -public class SharedPrefScriptFileList extends ScriptFileList { - - private static final Gson GSON = new Gson(); - - private static final String SP_KEY_SCRIPT_NAME = "script_name"; - private static final String SP_KEY_SCRIPT_PATH = "script_path"; - - private static ScriptFileList instance = new SharedPrefScriptFileList(App.getApp()); - - private SharedPreferences mSharedPreferences; - private List mScriptPath; - private List mScriptName; - - public static ScriptFileList getInstance() { - return instance; - } - - public SharedPrefScriptFileList(Context context) { - mSharedPreferences = context.getSharedPreferences("SharedPrefScriptFileList", Context.MODE_PRIVATE); - readFromSharedPref(); - } - - - private void readFromSharedPref() { - Type type = new TypeToken>() { - }.getType(); - mScriptName = GSON.fromJson(mSharedPreferences.getString(SP_KEY_SCRIPT_NAME, ""), type); - mScriptPath = GSON.fromJson(mSharedPreferences.getString(SP_KEY_SCRIPT_PATH, ""), type); - if (mScriptName == null || mScriptPath == null || mScriptName.size() != mScriptPath.size()) { - reset(); - } - } - - private void reset() { - mScriptName = new ArrayList<>(); - mScriptPath = new ArrayList<>(); - syncWithSharedPref(); - } - - @Override - public void add(ScriptFile scriptFile) { - mScriptName.add(scriptFile.getSimplifiedName()); - mScriptPath.add(scriptFile.getSimplifiedPath()); - syncWithSharedPref(); - } - - @Override - public ScriptFile get(int i) { - return new ScriptFile(mScriptPath.get(i)); - } - - @Override - public void remove(int i) { - mScriptName.remove(i); - mScriptPath.remove(i); - syncWithSharedPref(); - } - - @Override - public void rename(int position, String newName, boolean renameFile) { - mScriptName.set(position, newName); - if (renameFile) { - String newPath = PFile.renameWithoutExtensionAndReturnNewPath(mScriptPath.get(position), newName); - mScriptPath.set(position, newPath); - } - syncWithSharedPref(); - } - - @Override - public int size() { - return mScriptPath.size(); - } - - @Override - public boolean containsPath(String path) { - return mScriptPath.contains(path); - } - - protected void syncWithSharedPref() { - SharedPreferences.Editor editor = mSharedPreferences.edit(); - editor.putString(SP_KEY_SCRIPT_NAME, GSON.toJson(mScriptName)); - editor.putString(SP_KEY_SCRIPT_PATH, GSON.toJson(mScriptPath)); - editor.apply(); - } -} diff --git a/app/src/main/java/com/stardust/scriptdroid/script/StorageFileProvider.java b/app/src/main/java/com/stardust/scriptdroid/script/StorageFileProvider.java index 4b861374..742da390 100644 --- a/app/src/main/java/com/stardust/scriptdroid/script/StorageFileProvider.java +++ b/app/src/main/java/com/stardust/scriptdroid/script/StorageFileProvider.java @@ -125,7 +125,7 @@ public class StorageFileProvider { if (scriptFiles == null) { return Observable.empty(); } else { - FileSorter.sort(scriptFiles); + FileSorter.sort(scriptFiles, FileSorter.NAME); mScriptFileCache.put(dir.getPath(), scriptFiles); return Observable.fromArray(scriptFiles); } diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/edit/CodeMirrorEditor.java b/app/src/main/java/com/stardust/scriptdroid/ui/edit/CodeMirrorEditor.java index 4c132fba..47c936b3 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/edit/CodeMirrorEditor.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/edit/CodeMirrorEditor.java @@ -196,6 +196,7 @@ public class CodeMirrorEditor extends FrameLayout { public void loadFile(final File file) { setProgress(true); + // TODO: 2017/9/29 handle error Observable.fromCallable(new Callable() { @Override public String call() throws Exception { @@ -346,20 +347,22 @@ public class CodeMirrorEditor extends FrameLayout { @JavascriptInterface public void setStringFromJs(String text) { - if (mStringFromJs != null) { - mStringFromJs.onNext(text); - mStringFromJs.onComplete(); - mStringFromJs = null; + if (mStringFromJs == null) { + return; } + mStringFromJs.onNext(text); + mStringFromJs.onComplete(); + mStringFromJs = null; } @JavascriptInterface public void setIntFromJs(int i) { - if (mIntFromJs != null) { - mIntFromJs.onNext(i); - mIntFromJs.onComplete(); - mIntFromJs = null; + if (mIntFromJs == null) { + return; } + mIntFromJs.onNext(i); + mIntFromJs.onComplete(); + mIntFromJs = null; } @JavascriptInterface @@ -371,26 +374,28 @@ public class CodeMirrorEditor extends FrameLayout { @JavascriptInterface public void onTextChange() { - if (mCallback != null) { - mWebView.post(new Runnable() { - @Override - public void run() { - mCallback.onChange(); - } - }); + if (mCallback == null) { + return; } + mWebView.post(new Runnable() { + @Override + public void run() { + mCallback.onChange(); + } + }); } @JavascriptInterface public void updateCodeCompletion(final int fromLine, final int fromCh, final int toLine, final int toCh, final String[] list) { - if (mCallback != null) { - mWebView.post(new Runnable() { - @Override - public void run() { - mCallback.updateCodeCompletion(fromLine, fromCh, toLine, toCh, list); - } - }); + if (mCallback == null) { + return; } + mWebView.post(new Runnable() { + @Override + public void run() { + mCallback.updateCodeCompletion(fromLine, fromCh, toLine, toCh, list); + } + }); } } @@ -459,7 +464,7 @@ public class CodeMirrorEditor extends FrameLayout { @Override public void onProgressChanged(WebView view, int newProgress) { - mProgressBar.setVisibility(newProgress == 100 ? VISIBLE : GONE); + mProgressBar.setVisibility(newProgress == 100 ? GONE : VISIBLE); } } } diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/floating/EditorFloaty.java b/app/src/main/java/com/stardust/scriptdroid/ui/floating/EditorFloaty.java new file mode 100644 index 00000000..1cc50bf6 --- /dev/null +++ b/app/src/main/java/com/stardust/scriptdroid/ui/floating/EditorFloaty.java @@ -0,0 +1,105 @@ +package com.stardust.scriptdroid.ui.floating; + +import android.content.Context; +import android.content.Intent; +import android.support.annotation.Nullable; +import android.view.ContextThemeWrapper; +import android.view.View; + +import com.stardust.enhancedfloaty.FloatyService; +import com.stardust.enhancedfloaty.ResizableFloaty; +import com.stardust.enhancedfloaty.ResizableFloatyWindow; +import com.stardust.scriptdroid.R; +import com.stardust.scriptdroid.script.ScriptFile; +import com.stardust.scriptdroid.ui.edit.EditActivity_; +import com.stardust.scriptdroid.ui.edit.EditorView; + +import butterknife.BindView; +import butterknife.ButterKnife; +import butterknife.OnClick; + +import static com.stardust.scriptdroid.ui.edit.EditorView.EXTRA_NAME; +import static com.stardust.scriptdroid.ui.edit.EditorView.EXTRA_PATH; + +/** + * Created by Stardust on 2017/9/29. + */ + +public class EditorFloaty implements ResizableFloaty { + + private Intent mIntent; + + @BindView(R.id.resizer) + View mResizeIcon; + @BindView(R.id.move_cursor) + View mMoveIcon; + + private ResizableFloatyWindow mWindow; + + public EditorFloaty(Intent intent) { + mIntent = intent; + } + + public static void floatingEdit(Context context, Intent intent) { + FloatyService.addWindow(new ResizableFloatyWindow(new EditorFloaty(intent))); + context.startService(new Intent(context, FloatyService.class)); + } + + public static void floatingEdit(Context context, String path) { + floatingEdit(context, null, path); + } + + public static void floatingEdit(Context context, String name, String path) { + floatingEdit(context, new Intent(context, EditActivity_.class) + .putExtra(EXTRA_PATH, path) + .putExtra(EXTRA_NAME, name)); + } + + public static void floatingEdit(Context context, ScriptFile file) { + floatingEdit(context, file.getSimplifiedName(), file.getPath()); + } + + @Override + public View inflateView(FloatyService floatyService, ResizableFloatyWindow resizableFloatyWindow) { + mWindow = resizableFloatyWindow; + View v = View.inflate(new ContextThemeWrapper(floatyService, R.style.AppTheme), R.layout.floating_editor, null); + setUpViews(v); + return v; + } + + private void setUpViews(View v) { + EditorView editorView = (EditorView) v.findViewById(R.id.editor_view); + editorView.handleIntent(mIntent); + ButterKnife.bind(this, v); + } + + @OnClick(R.id.move_or_resize) + void showOrHideMoveAndResizeIcon() { + if (mResizeIcon.getVisibility() == View.VISIBLE) { + mResizeIcon.setVisibility(View.GONE); + mMoveIcon.setVisibility(View.GONE); + } else { + mResizeIcon.setVisibility(View.VISIBLE); + mMoveIcon.setVisibility(View.VISIBLE); + } + } + + @OnClick(R.id.close) + void close() { + mWindow.close(); + } + + @Nullable + @Override + public View getResizerView(View view) { + return view.findViewById(R.id.resizer); + } + + @Nullable + @Override + public View getMoveCursorView(View view) { + return view.findViewById(R.id.move_cursor); + } + + +} diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/main/scripts/MyScriptListFragment.java b/app/src/main/java/com/stardust/scriptdroid/ui/main/scripts/MyScriptListFragment.java index 6861fad3..bc814888 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/main/scripts/MyScriptListFragment.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/main/scripts/MyScriptListFragment.java @@ -16,6 +16,7 @@ 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.floating.EditorFloaty; import com.stardust.scriptdroid.ui.main.FloatingActionMenu; import com.stardust.scriptdroid.ui.main.ViewPagerFragment; import com.stardust.util.BackPressedHandler; @@ -56,7 +57,8 @@ public class MyScriptListFragment extends ViewPagerFragment implements BackPress mScriptFileList.setOnScriptFileClickListener(new ScriptListView.OnScriptFileClickListener() { @Override public void onScriptFileClick(View view, ScriptFile file) { - Scripts.edit(file); + //Scripts.edit(file); + EditorFloaty.floatingEdit(getContext(), file); } }); } @@ -112,6 +114,10 @@ public class MyScriptListFragment extends ViewPagerFragment implements BackPress mFloatingActionMenu.collapse(); return true; } + if(mScriptFileList.canGoBack()){ + mScriptFileList.goBack(); + return true; + } return false; } diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/main/scripts/ScriptListView.java b/app/src/main/java/com/stardust/scriptdroid/ui/main/scripts/ScriptListView.java index 07653aae..0b32ca31 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/main/scripts/ScriptListView.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/main/scripts/ScriptListView.java @@ -7,6 +7,7 @@ import android.support.v4.widget.SwipeRefreshLayout; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.AttributeSet; +import android.util.Log; import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; @@ -23,16 +24,24 @@ 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.viewmodel.ScriptList; import com.stardust.widget.BindableViewHolder; import org.greenrobot.eventbus.Subscribe; -import java.util.ArrayList; +import java.util.concurrent.Callable; import butterknife.BindView; import butterknife.ButterKnife; import butterknife.OnClick; +import io.reactivex.Observable; +import io.reactivex.ObservableSource; import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.annotations.NonNull; +import io.reactivex.functions.Action; +import io.reactivex.functions.BiConsumer; +import io.reactivex.functions.Consumer; +import io.reactivex.functions.Function; import io.reactivex.schedulers.Schedulers; /** @@ -46,14 +55,14 @@ public class ScriptListView extends SwipeRefreshLayout implements SwipeRefreshLa void onScriptFileClick(View view, ScriptFile file); } + private ScriptList mScriptList = new ScriptList(); private RecyclerView mScriptListView; private ScriptListAdapter mScriptListAdapter = new ScriptListAdapter(); - private ArrayList mScriptFiles = new ArrayList<>(); - private ArrayList mDirectories = new ArrayList<>(); private ScriptFile mCurrentDirectory; private OnScriptFileClickListener mOnScriptFileClickListener; private ScriptFile mSelectedScriptFile; private StorageFileProvider mStorageFileProvider; + private boolean mDirSortMenuShowing = false; public ScriptListView(Context context) { super(context); @@ -78,6 +87,16 @@ public class ScriptListView extends SwipeRefreshLayout implements SwipeRefreshLa mOnScriptFileClickListener = onScriptFileClickListener; } + + public boolean canGoBack() { + return !mCurrentDirectory.equals(mStorageFileProvider.getInitialDirectory()); + } + + public void goBack() { + mCurrentDirectory = mCurrentDirectory.getParentFile(); + loadScriptList(); + } + private void init() { setOnRefreshListener(this); mScriptListView = new RecyclerView(getContext()); @@ -95,7 +114,7 @@ public class ScriptListView extends SwipeRefreshLayout implements SwipeRefreshLa @Override public int getSpanSize(int position) { //For directories - if (position >= 1 && position <= mDirectories.size()) { + if (position >= 1 && position <= mScriptList.directoryCount()) { return 1; } //For files and category @@ -107,24 +126,30 @@ public class ScriptListView extends SwipeRefreshLayout implements SwipeRefreshLa private void loadScriptList() { - mScriptFiles.clear(); - mDirectories.clear(); + mScriptList.clear(); mStorageFileProvider.getDirectoryScriptFiles(mCurrentDirectory) .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new SimpleObserver() { - + .collectInto(mScriptList, new BiConsumer() { @Override - public void onNext(@io.reactivex.annotations.NonNull ScriptFile file) { - if (file.isFile()) { - mScriptFiles.add(file); - } else { - mDirectories.add(file); - } + public void accept(ScriptList list, ScriptFile file) throws Exception { + list.add(file); } - + }) + .observeOn(Schedulers.computation()) + .doOnSuccess(new Consumer() { @Override - public void onComplete() { + public void accept(@NonNull ScriptList list) throws Exception { + Log.d("SSS", "before sort:" + Thread.currentThread()); + list.sort(); + Log.d("SSS", "after sort:" + Thread.currentThread()); + } + }) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Consumer() { + @Override + public void accept(@NonNull ScriptList list) throws Exception { + Log.d("SSS", "notifyDataSetChanged:" + Thread.currentThread()); + mScriptList = list; mScriptListAdapter.notifyDataSetChanged(); setRefreshing(false); } @@ -166,16 +191,54 @@ public class ScriptListView extends SwipeRefreshLayout implements SwipeRefreshLa case R.id.open_by_other_apps: Scripts.openByOtherApps(mSelectedScriptFile); break; + case R.id.action_sort_by_date: + sort(ScriptList.SORT_TYPE_DATE, mDirSortMenuShowing); + break; + case R.id.action_sort_by_type: + sort(ScriptList.SORT_TYPE_TYPE, mDirSortMenuShowing); + break; + case R.id.action_sort_by_name: + sort(ScriptList.SORT_TYPE_NAME, mDirSortMenuShowing); + break; + case R.id.action_sort_by_size: + sort(ScriptList.SORT_TYPE_SIZE, mDirSortMenuShowing); + break; default: return false; } return true; } + private void sort(final int sortType, final boolean isDir) { + setRefreshing(true); + Observable.fromCallable(new Callable() { + @Override + public ScriptList call() throws Exception { + if (isDir) { + mScriptList.sortDir(sortType); + } else { + mScriptList.sortFile(sortType); + } + return mScriptList; + } + }) + + .subscribeOn(Schedulers.computation()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Consumer() { + @Override + public void accept(@NonNull ScriptList o) throws Exception { + mScriptListAdapter.notifyDataSetChanged(); + setRefreshing(false); + } + }); + } + + @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); - // mStorageFileProvider.unregisterDirectoryChangeListener(this); + // mStorageFileProvider.unregisterDirectoryChangeListener(this); } private class ScriptListAdapter extends RecyclerView.Adapter { @@ -202,23 +265,23 @@ public class ScriptListView extends SwipeRefreshLayout implements SwipeRefreshLa @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { BindableViewHolder bindableViewHolder = (BindableViewHolder) holder; - if (position == 0 || position == mDirectories.size() + 1) { + if (position == 0 || position == mScriptList.directoryCount() + 1) { bindableViewHolder.bind(position == 0, position); return; } - if (position <= mDirectories.size()) { - bindableViewHolder.bind(mDirectories.get(position - 1), position); + if (position <= mScriptList.directoryCount()) { + bindableViewHolder.bind(mScriptList.getDir(position - 1), position); return; } - bindableViewHolder.bind(mScriptFiles.get(position - mDirectories.size() - 2), position); + bindableViewHolder.bind(mScriptList.getFile(position - mScriptList.directoryCount() - 2), position); } @Override public int getItemViewType(int position) { - if (position == 0 || position == mDirectories.size() + 1) { + if (position == 0 || position == mScriptList.directoryCount() + 1) { return VIEW_TYPE_CATEGORY; } - if (position <= mDirectories.size()) { + if (position <= mScriptList.directoryCount()) { return VIEW_TYPE_DIRECTORY; } return VIEW_TYPE_FILE; @@ -226,7 +289,7 @@ public class ScriptListView extends SwipeRefreshLayout implements SwipeRefreshLa @Override public int getItemCount() { - return mScriptFiles.size() + mDirectories.size() + 2; + return mScriptList.count() + 2; } } @@ -338,6 +401,11 @@ public class ScriptListView extends SwipeRefreshLayout implements SwipeRefreshLa @BindView(R.id.sort) ImageView mSort; + @BindView(R.id.order) + ImageView mSortOrder; + + private boolean mIsDir; + CategoryViewHolder(View itemView) { super(itemView); ButterKnife.bind(this, itemView); @@ -346,11 +414,22 @@ public class ScriptListView extends SwipeRefreshLayout implements SwipeRefreshLa @Override public void bind(Boolean isDirCategory, int position) { mTitle.setText(isDirCategory ? R.string.text_directory : R.string.text_file); + mIsDir = isDirCategory; } @OnClick(R.id.order) void changeSortOrder() { - + if (mIsDir) { + mSortOrder.setImageResource(mScriptList.isDirSortedAscending() ? + R.drawable.ic_ascending_order : R.drawable.ic_descending_order); + mScriptList.setDirSortedAscending(!mScriptList.isDirSortedAscending()); + sort(mScriptList.getDirSortType(), mIsDir); + } else { + mSortOrder.setImageResource(mScriptList.isFileSortedAscending() ? + R.drawable.ic_ascending_order : R.drawable.ic_descending_order); + mScriptList.setFileSortedAscending(!mScriptList.isFileSortedAscending()); + sort(mScriptList.getFileSortType(), mIsDir); + } } @OnClick(R.id.sort) @@ -358,7 +437,9 @@ public class ScriptListView extends SwipeRefreshLayout implements SwipeRefreshLa PopupMenu popupMenu = new PopupMenu(getContext(), mSort); popupMenu.inflate(R.menu.menu_sort_options); popupMenu.setOnMenuItemClickListener(ScriptListView.this); + mDirSortMenuShowing = mIsDir; popupMenu.show(); + } } } diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/viewmodel/ScriptList.java b/app/src/main/java/com/stardust/scriptdroid/ui/viewmodel/ScriptList.java new file mode 100644 index 00000000..6cef647f --- /dev/null +++ b/app/src/main/java/com/stardust/scriptdroid/ui/viewmodel/ScriptList.java @@ -0,0 +1,113 @@ +package com.stardust.scriptdroid.ui.viewmodel; + +import com.stardust.scriptdroid.script.ScriptFile; +import com.stardust.util.FileSorter; + +import java.io.File; +import java.util.ArrayList; +import java.util.Comparator; + +/** + * Created by Stardust on 2017/9/30. + */ + +public class ScriptList { + + public static final int SORT_TYPE_NAME = 0x10; + public static final int SORT_TYPE_TYPE = 0x20; + public static final int SORT_TYPE_SIZE = 0x30; + public static final int SORT_TYPE_DATE = 0x40; + + private ArrayList mScriptFiles = new ArrayList<>(); + private ArrayList mDirectories = new ArrayList<>(); + private int mDirSortType = SORT_TYPE_NAME; + private boolean mDirSortedAscending; + private boolean mFileSortedAscending; + private int mFileSortType = SORT_TYPE_NAME; + + public boolean isDirSortedAscending() { + return mDirSortedAscending; + } + + public boolean isFileSortedAscending() { + return mFileSortedAscending; + } + + public int getDirSortType() { + return mDirSortType; + } + + public int getFileSortType() { + return mFileSortType; + } + + public void setDirSortedAscending(boolean dirSortedAscending) { + mDirSortedAscending = dirSortedAscending; + } + + public void setFileSortedAscending(boolean fileSortedAscending) { + mFileSortedAscending = fileSortedAscending; + } + + private Comparator getComparator(int sortType) { + switch (sortType) { + case SORT_TYPE_NAME: + return FileSorter.NAME; + case SORT_TYPE_DATE: + return FileSorter.DATE; + case SORT_TYPE_SIZE: + return FileSorter.SIZE; + case SORT_TYPE_TYPE: + return FileSorter.TYPE; + } + throw new IllegalArgumentException("unknown type " + sortType); + } + + public int directoryCount() { + return mDirectories.size(); + } + + public int fileCount() { + return mScriptFiles.size(); + } + + public void clear() { + mScriptFiles.clear(); + mDirectories.clear(); + } + + public void add(ScriptFile file) { + if (file.isFile()) { + mScriptFiles.add(file); + } else { + mDirectories.add(file); + } + } + + public ScriptFile getDir(int i) { + return mDirectories.get(i); + } + + public ScriptFile getFile(int i) { + return mScriptFiles.get(i); + } + + public int count() { + return mScriptFiles.size() + mDirectories.size(); + } + + public void sortDir(int sortType) { + mDirSortType = sortType; + FileSorter.sort(mDirectories, getComparator(sortType), mDirSortedAscending); + } + + public void sortFile(int sortType) { + mFileSortType = sortType; + FileSorter.sort(mScriptFiles, getComparator(sortType), mFileSortedAscending); + } + + public void sort() { + FileSorter.sort(mDirectories, getComparator(mDirSortType), mDirSortedAscending); + FileSorter.sort(mScriptFiles, getComparator(mFileSortType), mFileSortedAscending); + } +} diff --git a/app/src/main/java/com/stardust/widget/EWebView.java b/app/src/main/java/com/stardust/widget/EWebView.java index ee157bf8..52014e8f 100644 --- a/app/src/main/java/com/stardust/widget/EWebView.java +++ b/app/src/main/java/com/stardust/widget/EWebView.java @@ -59,6 +59,7 @@ public class EWebView extends FrameLayout implements SwipeRefreshLayout.OnRefres settings.setJavaScriptEnabled(true); settings.setJavaScriptCanOpenWindowsAutomatically(true); settings.setDomStorageEnabled(true); + settings.setDisplayZoomControls(false); mWebView.setWebViewClient(new MyWebViewClient()); mWebView.setWebChromeClient(new MyWebChromeClient()); } diff --git a/app/src/main/res/layout/floating_editor.xml b/app/src/main/res/layout/floating_editor.xml new file mode 100644 index 00000000..6b712330 --- /dev/null +++ b/app/src/main/res/layout/floating_editor.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/menu_sort_options.xml b/app/src/main/res/menu/menu_sort_options.xml index 9857573f..5d9e3737 100644 --- a/app/src/main/res/menu/menu_sort_options.xml +++ b/app/src/main/res/menu/menu_sort_options.xml @@ -2,18 +2,18 @@ \ 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 b8726f5e..a8be6c87 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -279,6 +279,8 @@ 重构 选择变量 显示变量类型 + 关闭 + 调整 diff --git a/app/src/test/java/com/stardust/scriptdroid/ExampleUnitTest.java b/app/src/test/java/com/stardust/scriptdroid/ExampleUnitTest.java index 69cdd4e6..abcf56e7 100644 --- a/app/src/test/java/com/stardust/scriptdroid/ExampleUnitTest.java +++ b/app/src/test/java/com/stardust/scriptdroid/ExampleUnitTest.java @@ -2,6 +2,15 @@ package com.stardust.scriptdroid; import org.junit.Test; +import java.util.concurrent.Callable; + +import io.reactivex.Observable; +import io.reactivex.annotations.NonNull; +import io.reactivex.functions.Action; +import io.reactivex.functions.Consumer; +import io.reactivex.functions.Function; +import io.reactivex.schedulers.Schedulers; + /** * Example local unit test, which will execute on the development machine (host). * @@ -17,11 +26,33 @@ public class ExampleUnitTest { // TODO: 2017/7/4 细节 三天 7.18 // TODO: 2017/7/4 写文档 两天 7.20 // TODO: 2017/7/4 发布 3.0.0 Beta 7.22 + // TODO: 2017/9/30 想象真是美好。 @Test public void test() { - System.out.println("SOS".hashCode()); + Observable.fromCallable(new Callable() { + @Override + public String call() throws Exception { + System.out.println(Thread.currentThread()); + return ""; + } + }) + .subscribeOn(Schedulers.io()) + .observeOn(Schedulers.newThread()) + .doOnComplete(new Action() { + @Override + public void run() throws Exception { + System.out.println(Thread.currentThread()); + } + }) + .observeOn(Schedulers.newThread()) + .subscribe(new Consumer() { + @Override + public void accept(@NonNull String s) throws Exception { + System.out.println(Thread.currentThread()); + } + }); } @Test diff --git a/common/src/main/java/com/stardust/util/FileSorter.java b/common/src/main/java/com/stardust/util/FileSorter.java index 020e0440..d22bdacd 100644 --- a/common/src/main/java/com/stardust/util/FileSorter.java +++ b/common/src/main/java/com/stardust/util/FileSorter.java @@ -1,9 +1,14 @@ package com.stardust.util; +import com.stardust.pio.PFile; + import java.io.File; import java.text.Collator; import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; import java.util.Comparator; +import java.util.List; import java.util.Locale; /** @@ -12,16 +17,72 @@ import java.util.Locale; public class FileSorter { - public static void sort(File[] files) { + public static final Comparator NAME = new Comparator() { final Collator collator = Collator.getInstance(); - Arrays.sort(files, new Comparator() { - @Override - public int compare(File o1, File o2) { - if (o1.isDirectory() != o2.isDirectory()) - return o1.isDirectory() ? Integer.MIN_VALUE : Integer.MAX_VALUE; - return collator.compare(o1.getName(), o2.getName()); - } - }); + + @Override + public int compare(File o1, File o2) { + if (o1.isDirectory() != o2.isDirectory()) + return o1.isDirectory() ? Integer.MIN_VALUE : Integer.MAX_VALUE; + return -collator.compare(o1.getName(), o2.getName()); + } + }; + + public static final Comparator DATE = new Comparator() { + @Override + public int compare(File o1, File o2) { + return o1.lastModified() == o2.lastModified() ? 0 : + o1.lastModified() > o2.lastModified() ? 1 : -1; + } + }; + + public static final Comparator TYPE = new Comparator() { + @Override + public int compare(File o1, File o2) { + return -PFile.getExtension(o1.getName()).compareTo(PFile.getExtension(o2.getName())); + } + }; + + public static final Comparator SIZE = new Comparator() { + @Override + public int compare(File o1, File o2) { + return o1.length() == o2.length() ? 0 : + o1.length() < o2.length() ? 1 : -1; + } + }; + + public static void sort(File[] files, final Comparator comparator, boolean ascending) { + if (ascending) { + Arrays.sort(files, comparator); + } else { + Arrays.sort(files, new Comparator() { + @Override + public int compare(File o1, File o2) { + return comparator.compare(o2, o1); + } + }); + } + } + + public static void sort(File[] files, Comparator comparator) { + sort(files, comparator, true); + } + + public static void sort(List files, final Comparator comparator, boolean ascending) { + if (ascending) { + Collections.sort(files, comparator); + } else { + Collections.sort(files, new Comparator() { + @Override + public int compare(File o1, File o2) { + return comparator.compare(o2, o1); + } + }); + } + } + + public static void sort(List files, Comparator comparator) { + sort(files, comparator, true); } }