From 37796048f4f10a32f265e92dc930e2145488048e Mon Sep 17 00:00:00 2001 From: hyb1996 <946994919@qq.com> Date: Mon, 17 Sep 2018 09:24:22 +0800 Subject: [PATCH] refactor(ui): refactor ScriptListView --- app/src/main/java/org/autojs/autojs/Pref.java | 13 +- .../autojs/autojs/external/ScriptIntents.java | 5 +- .../external/tasker/TaskPrefEditActivity.java | 25 +- .../widget/ScriptWidgetSettingsActivity.java | 28 +- .../autojs/model/explorer/Explorer.java | 114 ++++++ .../model/explorer/ExplorerChangeEvent.java | 49 +++ .../model/explorer/ExplorerDirPage.java | 88 +++++ .../model/explorer/ExplorerFileItem.java | 84 ++++ .../model/explorer/ExplorerFileProvider.java | 57 +++ .../autojs/model/explorer/ExplorerItem.java | 31 ++ .../autojs/model/explorer/ExplorerPage.java | 17 + .../model/explorer/ExplorerProvider.java | 8 + .../model/explorer/ExplorerSamplePage.java | 33 ++ .../autojs/model/explorer/ExplorerSorter.java | 44 +++ .../autojs/model/explorer/Explorers.java | 21 + .../model/explorer/WorkspaceFileProvider.java | 95 +++++ .../autojs/autojs/model/script/Scripts.java | 10 +- .../DevPluginResponseHandler.java | 4 +- .../storage/file/SampleFileProvider.java | 74 ---- .../storage/file/StorageFileProvider.java | 231 ----------- .../autojs/timing/TimedTaskManager.java | 4 +- .../autojs/autojs/ui/build/BuildActivity.java | 8 +- .../autojs/ui/common/ScriptOperations.java | 51 ++- .../ui/explorer/ExplorerViewHelper.java | 67 ++++ .../ui/filechooser/FileChooseListView.java | 76 ++-- .../filechooser/FileChooserDialogBuilder.java | 48 ++- .../autojs/ui/floating/CircularMenu.java | 19 +- .../autojs/autojs/ui/main/MainActivity.java | 61 ++- .../ui/main/community/CommunityWebView.java | 5 +- ...eListFragment.java => MarketFragment.java} | 26 +- .../autojs/ui/main/sample/SampleListView.java | 148 ------- ...{ScriptListView.java => ExplorerView.java} | 374 ++++++++++-------- .../ui/main/scripts/MyScriptListFragment.java | 54 +-- .../ui/settings/ScriptDirPathPreference.java | 13 +- .../ui/update/UpdateInfoDialogBuilder.java | 6 +- ...{ScriptList.java => ExplorerItemList.java} | 67 ++-- .../main/res/drawable-xhdpi/ic_sample_dir.png | Bin 0 -> 2496 bytes .../activity_script_widget_settings.xml | 2 +- .../main/res/layout/activity_tasker_edit.xml | 2 +- ...nt_sample_list.xml => fragment_market.xml} | 4 - .../res/layout/fragment_my_script_list.xml | 2 +- .../res/layout/script_file_list_directory.xml | 5 +- app/src/main/res/values/strings.xml | 2 +- .../main/assets/modules/__RootAutomator__.js | 5 +- .../core/inputevent/InputEventCodes.java | 4 + .../autojs/core/inputevent/RootAutomator.java | 22 +- .../autojs/engine/RootAutomatorEngine.java | 2 +- common/release/output.json | 2 +- 48 files changed, 1219 insertions(+), 891 deletions(-) create mode 100644 app/src/main/java/org/autojs/autojs/model/explorer/Explorer.java create mode 100644 app/src/main/java/org/autojs/autojs/model/explorer/ExplorerChangeEvent.java create mode 100644 app/src/main/java/org/autojs/autojs/model/explorer/ExplorerDirPage.java create mode 100644 app/src/main/java/org/autojs/autojs/model/explorer/ExplorerFileItem.java create mode 100644 app/src/main/java/org/autojs/autojs/model/explorer/ExplorerFileProvider.java create mode 100644 app/src/main/java/org/autojs/autojs/model/explorer/ExplorerItem.java create mode 100644 app/src/main/java/org/autojs/autojs/model/explorer/ExplorerPage.java create mode 100644 app/src/main/java/org/autojs/autojs/model/explorer/ExplorerProvider.java create mode 100644 app/src/main/java/org/autojs/autojs/model/explorer/ExplorerSamplePage.java create mode 100644 app/src/main/java/org/autojs/autojs/model/explorer/ExplorerSorter.java create mode 100644 app/src/main/java/org/autojs/autojs/model/explorer/Explorers.java create mode 100644 app/src/main/java/org/autojs/autojs/model/explorer/WorkspaceFileProvider.java delete mode 100644 app/src/main/java/org/autojs/autojs/storage/file/SampleFileProvider.java delete mode 100644 app/src/main/java/org/autojs/autojs/storage/file/StorageFileProvider.java create mode 100644 app/src/main/java/org/autojs/autojs/ui/explorer/ExplorerViewHelper.java rename app/src/main/java/org/autojs/autojs/ui/main/sample/{SampleListFragment.java => MarketFragment.java} (67%) delete mode 100644 app/src/main/java/org/autojs/autojs/ui/main/sample/SampleListView.java rename app/src/main/java/org/autojs/autojs/ui/main/scripts/{ScriptListView.java => ExplorerView.java} (52%) rename app/src/main/java/org/autojs/autojs/ui/viewmodel/{ScriptList.java => ExplorerItemList.java} (71%) create mode 100644 app/src/main/res/drawable-xhdpi/ic_sample_dir.png rename app/src/main/res/layout/{fragment_sample_list.xml => fragment_market.xml} (61%) diff --git a/app/src/main/java/org/autojs/autojs/Pref.java b/app/src/main/java/org/autojs/autojs/Pref.java index c147dbd4..19121fde 100644 --- a/app/src/main/java/org/autojs/autojs/Pref.java +++ b/app/src/main/java/org/autojs/autojs/Pref.java @@ -2,6 +2,7 @@ package org.autojs.autojs; import android.content.Context; import android.content.SharedPreferences; +import android.os.Environment; import android.preference.PreferenceManager; import com.stardust.app.GlobalAppContext; @@ -9,6 +10,7 @@ import com.stardust.autojs.runtime.accessibility.AccessibilityConfig; import org.autojs.autojs.autojs.key.GlobalKeyObserver; +import java.io.File; import java.util.concurrent.TimeUnit; /** @@ -98,7 +100,7 @@ public class Pref { } public static boolean shouldShowAd() { - if(isFirstDay() && !BuildConfig.DEBUG){ + if (isFirstDay() && !BuildConfig.DEBUG) { return false; } String adShowingMode = def().getString(getString(R.string.key_ad_showing_mode), "Default"); @@ -116,10 +118,10 @@ public class Pref { return true; } - public static int getAdType(){ + public static int getAdType() { try { return Integer.parseInt(def().getString(getString(R.string.key_ad_type), String.valueOf(Constants.AD_TYPE_RANDOM))); - }catch (Exception e){ + } catch (Exception e) { e.printStackTrace(); return Constants.AD_TYPE_RANDOM; } @@ -127,7 +129,7 @@ public class Pref { private static boolean isFirstDay() { long firstUsingMillis = def().getLong("firstUsingMillis", -1); - if(firstUsingMillis == -1){ + if (firstUsingMillis == -1) { def().edit().putLong("firstUsingMillis", System.currentTimeMillis()).apply(); return true; } @@ -195,7 +197,8 @@ public class Pref { } public static String getScriptDirPath() { - return def().getString(getString(R.string.key_script_dir_path), + String dir = def().getString(getString(R.string.key_script_dir_path), getString(R.string.default_value_script_dir_path)); + return new File(Environment.getExternalStorageDirectory(), dir).getPath(); } } diff --git a/app/src/main/java/org/autojs/autojs/external/ScriptIntents.java b/app/src/main/java/org/autojs/autojs/external/ScriptIntents.java index 6bca5756..713c97e3 100644 --- a/app/src/main/java/org/autojs/autojs/external/ScriptIntents.java +++ b/app/src/main/java/org/autojs/autojs/external/ScriptIntents.java @@ -9,8 +9,9 @@ import com.stardust.autojs.script.JavaScriptFileSource; import com.stardust.autojs.script.ScriptSource; import com.stardust.autojs.script.SequenceScriptSource; import com.stardust.autojs.script.StringScriptSource; + +import org.autojs.autojs.Pref; import org.autojs.autojs.autojs.AutoJs; -import org.autojs.autojs.storage.file.StorageFileProvider; import org.autojs.autojs.model.script.PathChecker; import java.io.File; @@ -51,7 +52,7 @@ public class ScriptIntents { } config.executePath(new File(path).getParent()); } else { - config.executePath(StorageFileProvider.getDefaultDirectoryPath()); + config.executePath(Pref.getScriptDirPath()); } if (source == null) { return false; diff --git a/app/src/main/java/org/autojs/autojs/external/tasker/TaskPrefEditActivity.java b/app/src/main/java/org/autojs/autojs/external/tasker/TaskPrefEditActivity.java index 8e4381c0..d8d93948 100644 --- a/app/src/main/java/org/autojs/autojs/external/tasker/TaskPrefEditActivity.java +++ b/app/src/main/java/org/autojs/autojs/external/tasker/TaskPrefEditActivity.java @@ -2,23 +2,24 @@ package org.autojs.autojs.external.tasker; import android.content.Intent; import android.os.Bundle; +import android.os.Environment; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.text.TextUtils; import android.view.Menu; import android.view.MenuItem; -import org.autojs.autojs.R; -import org.autojs.autojs.external.ScriptIntents; -import org.autojs.autojs.model.script.ScriptFile; -import org.autojs.autojs.storage.file.StorageFileProvider; -import org.autojs.autojs.ui.BaseActivity; -import org.autojs.autojs.ui.main.scripts.ScriptListView; import com.twofortyfouram.locale.sdk.client.ui.activity.AbstractAppCompatPluginActivity; import org.androidannotations.annotations.AfterViews; import org.androidannotations.annotations.Click; import org.androidannotations.annotations.EActivity; +import org.autojs.autojs.R; +import org.autojs.autojs.external.ScriptIntents; +import org.autojs.autojs.model.explorer.ExplorerDirPage; +import org.autojs.autojs.model.explorer.Explorers; +import org.autojs.autojs.ui.BaseActivity; +import org.autojs.autojs.ui.main.scripts.ExplorerView; import static org.autojs.autojs.ui.edit.EditorView.EXTRA_CONTENT; @@ -31,7 +32,6 @@ public class TaskPrefEditActivity extends AbstractAppCompatPluginActivity { private String mSelectedScriptFilePath; private String mPreExecuteScript; - private StorageFileProvider mStorageFileProvider; @AfterViews void setUpViews() { @@ -41,11 +41,10 @@ public class TaskPrefEditActivity extends AbstractAppCompatPluginActivity { private void initScriptListRecyclerView() { - mStorageFileProvider = StorageFileProvider.getExternalStorageProvider(); - ScriptListView scriptList = (ScriptListView) findViewById(R.id.script_list); - scriptList.setStorageFileProvider(mStorageFileProvider, new ScriptFile(StorageFileProvider.getDefaultDirectory())); - scriptList.setOnScriptFileClickListener((view, file) -> { - mSelectedScriptFilePath = file.getPath(); + ExplorerView explorerView = (ExplorerView) findViewById(R.id.script_list); + explorerView.setExplorer(Explorers.external(), ExplorerDirPage.createRoot(Environment.getExternalStorageDirectory())); + explorerView.setOnItemClickListener((view, item) -> { + mSelectedScriptFilePath = item.getPath(); finish(); }); } @@ -59,7 +58,7 @@ public class TaskPrefEditActivity extends AbstractAppCompatPluginActivity { @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == R.id.action_refresh) { - mStorageFileProvider.refreshAll(); + Explorers.external().refreshAll(); } else if (item.getItemId() == R.id.action_clear_file_selection) { mSelectedScriptFilePath = null; } else { diff --git a/app/src/main/java/org/autojs/autojs/external/widget/ScriptWidgetSettingsActivity.java b/app/src/main/java/org/autojs/autojs/external/widget/ScriptWidgetSettingsActivity.java index 8a942c45..40c05ac2 100644 --- a/app/src/main/java/org/autojs/autojs/external/widget/ScriptWidgetSettingsActivity.java +++ b/app/src/main/java/org/autojs/autojs/external/widget/ScriptWidgetSettingsActivity.java @@ -3,18 +3,20 @@ package org.autojs.autojs.external.widget; import android.appwidget.AppWidgetManager; import android.content.Intent; import android.os.Bundle; +import android.os.Environment; import android.support.annotation.Nullable; import android.view.Menu; import android.view.MenuItem; -import org.autojs.autojs.R; -import org.autojs.autojs.model.script.ScriptFile; -import org.autojs.autojs.storage.file.StorageFileProvider; -import org.autojs.autojs.ui.BaseActivity; -import org.autojs.autojs.ui.main.scripts.ScriptListView; - import org.androidannotations.annotations.AfterViews; import org.androidannotations.annotations.EActivity; +import org.autojs.autojs.R; +import org.autojs.autojs.model.explorer.Explorer; +import org.autojs.autojs.model.explorer.ExplorerDirPage; +import org.autojs.autojs.model.explorer.ExplorerFileProvider; +import org.autojs.autojs.model.script.Scripts; +import org.autojs.autojs.ui.BaseActivity; +import org.autojs.autojs.ui.main.scripts.ExplorerView; /** * Created by Stardust on 2017/7/11. @@ -22,9 +24,8 @@ import org.androidannotations.annotations.EActivity; @EActivity(R.layout.activity_script_widget_settings) public class ScriptWidgetSettingsActivity extends BaseActivity { - private String mSelectedScriptFilePath; - private StorageFileProvider mStorageFileProvider; + private Explorer mExplorer; private int mAppWidgetId; @Override @@ -41,11 +42,10 @@ public class ScriptWidgetSettingsActivity extends BaseActivity { private void initScriptListRecyclerView() { - mStorageFileProvider = StorageFileProvider.getExternalStorageProvider(); - ScriptListView scriptList = (ScriptListView) findViewById(R.id.script_list); - scriptList.setStorageFileProvider(mStorageFileProvider); - scriptList.setCurrentDirectory(new ScriptFile(StorageFileProvider.getDefaultDirectory())); - scriptList.setOnScriptFileClickListener((view, file) -> { + mExplorer = new Explorer(new ExplorerFileProvider(Scripts.FILE_FILTER), 0); + ExplorerView explorerView = (ExplorerView) findViewById(R.id.script_list); + explorerView.setExplorer(mExplorer, ExplorerDirPage.createRoot(Environment.getExternalStorageDirectory())); + explorerView.setOnItemClickListener((view, file) -> { mSelectedScriptFilePath = file.getPath(); finish(); }); @@ -55,7 +55,7 @@ public class ScriptWidgetSettingsActivity extends BaseActivity { @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == R.id.action_refresh) { - mStorageFileProvider.refreshAll(); + mExplorer.refreshAll(); } else if (item.getItemId() == R.id.action_clear_file_selection) { mSelectedScriptFilePath = null; } diff --git a/app/src/main/java/org/autojs/autojs/model/explorer/Explorer.java b/app/src/main/java/org/autojs/autojs/model/explorer/Explorer.java new file mode 100644 index 00000000..4b19386c --- /dev/null +++ b/app/src/main/java/org/autojs/autojs/model/explorer/Explorer.java @@ -0,0 +1,114 @@ +package org.autojs.autojs.model.explorer; + +import android.support.annotation.Nullable; +import android.util.LruCache; + +import com.stardust.pio.PFile; + +import org.greenrobot.eventbus.EventBus; + +import io.reactivex.Single; +import io.reactivex.android.schedulers.AndroidSchedulers; + +import static org.autojs.autojs.model.explorer.ExplorerChangeEvent.*; + + +public class Explorer { + + private final ExplorerProvider mExplorerProvider; + private final EventBus mEventBus; + @Nullable + private final LruCache mExplorerPageLruCache; + + public Explorer(ExplorerProvider explorerProvider, int cacheSize, EventBus eventBus) { + mExplorerPageLruCache = cacheSize <= 0 ? null : new LruCache<>(cacheSize); + mExplorerProvider = explorerProvider; + mEventBus = eventBus; + } + + public Explorer(ExplorerProvider explorerProvider, int cacheSize) { + this(explorerProvider, cacheSize, EventBus.getDefault()); + } + + public void notifyChildrenChanged(ExplorerPage itemGroup) { + clearCache(itemGroup); + mEventBus.post(new ExplorerChangeEvent(itemGroup)); + } + + public void notifyItemChanged(ExplorerItem oldItem, ExplorerItem newItem) { + ExplorerPage itemGroup = getParentFromCache(oldItem); + if (itemGroup != null) { + itemGroup.updateChild(oldItem, newItem); + } + mEventBus.post(new ExplorerChangeEvent(oldItem.getParent(), CHANGE, oldItem, newItem)); + } + + private ExplorerPage getParentFromCache(ExplorerItem item) { + if (mExplorerPageLruCache == null) { + return null; + } + ExplorerPage parent = item.getParent(); + if (parent == null) { + if (item instanceof ExplorerFileItem) { + PFile parentFile = ((ExplorerFileItem) item).getFile().getParentFile(); + return parentFile == null ? null : mExplorerPageLruCache.get(parentFile.getPath()); + } + return null; + } + return mExplorerPageLruCache.get(parent.getPath()); + } + + + public void notifyItemRemoved(ExplorerItem item) { + ExplorerPage itemGroup = getParentFromCache(item); + if (itemGroup != null) { + itemGroup.removeChild(item); + } + mEventBus.post(new ExplorerChangeEvent(item.getParent(), REMOVE, item)); + } + + public void notifyItemCreated(ExplorerItem item) { + ExplorerPage itemGroup = getParentFromCache(item); + if (itemGroup != null) { + itemGroup.addChild(item); + } + mEventBus.post(new ExplorerChangeEvent(item.getParent(), CREATE, item)); + } + + @SuppressWarnings("unchecked") + public void refreshAll() { + if (mExplorerPageLruCache != null) + mExplorerPageLruCache.evictAll(); + mEventBus.post(new ExplorerChangeEvent(ALL)); + } + + + public Single fetchChildren(ExplorerPage page) { + ExplorerPage cachedGroup = mExplorerPageLruCache.get(page.getPath()); + if (cachedGroup != null) { + page.copyChildren(cachedGroup); + return Single.just(page); + } + return mExplorerProvider.getExplorerPage(page) + .observeOn(AndroidSchedulers.mainThread()) + .map(g -> { + mExplorerPageLruCache.put(g.getPath(), g); + page.copyChildren(g); + return page; + }); + } + + private void clearCache(ExplorerPage item) { + if (mExplorerPageLruCache != null) + mExplorerPageLruCache.remove(item.getPath()); + } + + public void registerChangeListener(Object subscriber) { + if (!mEventBus.isRegistered(subscriber)) + mEventBus.register(subscriber); + } + + public void unregisterChangeListener(Object subscriber) { + mEventBus.unregister(subscriber); + } +} diff --git a/app/src/main/java/org/autojs/autojs/model/explorer/ExplorerChangeEvent.java b/app/src/main/java/org/autojs/autojs/model/explorer/ExplorerChangeEvent.java new file mode 100644 index 00000000..cb0ca72c --- /dev/null +++ b/app/src/main/java/org/autojs/autojs/model/explorer/ExplorerChangeEvent.java @@ -0,0 +1,49 @@ +package org.autojs.autojs.model.explorer; + +public class ExplorerChangeEvent { + + public static final int REMOVE = 0; + public static final int CREATE = 1; + public static final int CHANGE = 2; + public static final int ALL = 3; + + private final int mAction; + private final ExplorerItem mItem; + private final ExplorerItem mNewItem; + private final ExplorerPage mItemGroup; + + public ExplorerChangeEvent(ExplorerPage itemGroup) { + this(itemGroup, CHANGE, null, null); + } + + public ExplorerChangeEvent(ExplorerPage parent, int action, ExplorerItem oldItem, ExplorerItem newItem) { + mAction = action; + mItemGroup = parent; + mNewItem = newItem; + mItem = oldItem; + } + + public ExplorerChangeEvent(ExplorerPage parent, int action, ExplorerItem item) { + this(parent, action, item, null); + } + + public ExplorerChangeEvent(int action) { + this(null, action, null, null); + } + + public int getAction() { + return mAction; + } + + public ExplorerItem getItem() { + return mItem; + } + + public ExplorerItem getNewItem() { + return mNewItem; + } + + public ExplorerPage getItemGroup() { + return mItemGroup; + } +} diff --git a/app/src/main/java/org/autojs/autojs/model/explorer/ExplorerDirPage.java b/app/src/main/java/org/autojs/autojs/model/explorer/ExplorerDirPage.java new file mode 100644 index 00000000..7348c169 --- /dev/null +++ b/app/src/main/java/org/autojs/autojs/model/explorer/ExplorerDirPage.java @@ -0,0 +1,88 @@ +package org.autojs.autojs.model.explorer; + +import android.os.Build; +import android.support.annotation.NonNull; +import android.support.annotation.RequiresApi; + +import com.stardust.pio.PFile; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Spliterator; +import java.util.function.Consumer; + +public class ExplorerDirPage extends ExplorerFileItem implements ExplorerPage { + + private List mChildren = Collections.emptyList(); + + public ExplorerDirPage(PFile file, ExplorerPage parent) { + super(file, parent); + } + + public ExplorerDirPage(String path, ExplorerPage parent) { + super(path, parent); + } + + public ExplorerDirPage(File file, ExplorerPage parent) { + super(file, parent); + } + + public void copyChildren(ExplorerPage g) { + ensureChildListWritable(); + mChildren.clear(); + mChildren.addAll(((ExplorerDirPage) g).mChildren); + } + + private void ensureChildListWritable() { + if (mChildren == Collections.EMPTY_LIST) { + mChildren = new ArrayList<>(); + } + } + + public boolean updateChild(ExplorerItem oldItem, ExplorerItem newItem) { + int i = mChildren.indexOf(oldItem); + if (i < 0) { + return false; + } + mChildren.set(i, newItem); + return true; + } + + public boolean removeChild(ExplorerItem item) { + return mChildren.remove(item); + } + + public void addChild(ExplorerItem item) { + ensureChildListWritable(); + mChildren.add(item); + } + + @NonNull + @Override + public Iterator iterator() { + return mChildren.iterator(); + } + + @RequiresApi(api = Build.VERSION_CODES.N) + @Override + public void forEach(Consumer action) { + mChildren.forEach(action); + } + + @RequiresApi(api = Build.VERSION_CODES.N) + @Override + public Spliterator spliterator() { + return mChildren.spliterator(); + } + + public static ExplorerDirPage createRoot(String path){ + return new ExplorerDirPage(path, null); + } + + public static ExplorerPage createRoot(File directory) { + return new ExplorerDirPage(directory, null); + } +} diff --git a/app/src/main/java/org/autojs/autojs/model/explorer/ExplorerFileItem.java b/app/src/main/java/org/autojs/autojs/model/explorer/ExplorerFileItem.java new file mode 100644 index 00000000..f47b03af --- /dev/null +++ b/app/src/main/java/org/autojs/autojs/model/explorer/ExplorerFileItem.java @@ -0,0 +1,84 @@ +package org.autojs.autojs.model.explorer; + +import android.graphics.Color; + +import com.stardust.pio.PFile; + +import org.autojs.autojs.model.script.ScriptFile; + +import java.io.File; + +public class ExplorerFileItem implements ExplorerItem { + + private final PFile mFile; + private final ExplorerPage mParent; + + public ExplorerFileItem(PFile file, ExplorerPage parent) { + mFile = file; + mParent = parent; + } + + public ExplorerFileItem(String path, ExplorerPage parent) { + mFile = new PFile(path); + mParent = parent; + } + + public ExplorerFileItem(File file, ExplorerPage parent) { + mFile = new PFile(file.getPath()); + mParent = parent; + } + + public PFile getFile() { + return mFile; + } + + @Override + public String getName() { + return mFile.getName(); + } + + @Override + public ExplorerPage getParent() { + return mParent; + } + + @Override + public String getPath() { + return mFile.getPath(); + } + + @Override + public long lastModified() { + return mFile.lastModified(); + } + + @Override + public String getType() { + if(mFile.isDirectory()){ + return "/"; + } + return mFile.getExtension(); + } + + @Override + public long getSize() { + return mFile.length(); + } + + @Override + public ScriptFile toScriptFile() { + return new ScriptFile(mFile); + } + + @Override + public boolean isEditable() { + String type = getType(); + return type.equals("js") || type.equals("json") || type.equals("xml"); + } + + @Override + public boolean isExecutable() { + String type = getType(); + return type.equals("js") || type.equals("auto"); + } +} diff --git a/app/src/main/java/org/autojs/autojs/model/explorer/ExplorerFileProvider.java b/app/src/main/java/org/autojs/autojs/model/explorer/ExplorerFileProvider.java new file mode 100644 index 00000000..02885552 --- /dev/null +++ b/app/src/main/java/org/autojs/autojs/model/explorer/ExplorerFileProvider.java @@ -0,0 +1,57 @@ +package org.autojs.autojs.model.explorer; + +import com.stardust.pio.PFile; + +import java.io.FileFilter; + +import io.reactivex.Observable; +import io.reactivex.Single; +import io.reactivex.schedulers.Schedulers; + +public class ExplorerFileProvider implements ExplorerProvider { + + private final FileFilter mFileFilter; + + public ExplorerFileProvider(FileFilter fileFilter) { + mFileFilter = fileFilter; + } + + public ExplorerFileProvider() { + this(null); + } + + @Override + public Single getExplorerPage(ExplorerPage page) { + ExplorerPage parent = page.getParent(); + String path = page.getPath(); + return listFiles(new PFile(path)) + .collectInto(createExplorerPage(path, parent), (p, file) -> { + if(file.isDirectory()){ + p.addChild(new ExplorerDirPage(file, p)); + }else { + p.addChild(new ExplorerFileItem(file, p)); + } + }) + .subscribeOn(Schedulers.io()); + } + + protected ExplorerDirPage createExplorerPage(String path, ExplorerPage parent) { + return new ExplorerDirPage(path, parent); + } + + protected Observable listFiles(PFile directory) { + return Observable.just(directory) + .flatMap(dir -> { + PFile[] files; + if (mFileFilter == null) { + files = dir.listFiles(); + } else { + files = dir.listFiles(mFileFilter); + } + if (files == null) { + return Observable.empty(); + } + return Observable.fromArray(files); + }); + } +} diff --git a/app/src/main/java/org/autojs/autojs/model/explorer/ExplorerItem.java b/app/src/main/java/org/autojs/autojs/model/explorer/ExplorerItem.java new file mode 100644 index 00000000..60507f0f --- /dev/null +++ b/app/src/main/java/org/autojs/autojs/model/explorer/ExplorerItem.java @@ -0,0 +1,31 @@ +package org.autojs.autojs.model.explorer; + +import org.autojs.autojs.model.script.ScriptFile; + +public interface ExplorerItem { + + String TYPE_DIRECTORY = "/"; + String TYPE_JAVASCRIPT = "js"; + String TYPE_AUTO_FILE = "auto"; + String TYPE_JSON = "json"; + String TYPE_XML = "xml"; + String TYPE_UNKNOWN = "?"; + + String getName(); + + ExplorerPage getParent(); + + String getPath(); + + long lastModified(); + + String getType(); + + long getSize(); + + ScriptFile toScriptFile(); + + boolean isEditable(); + + boolean isExecutable(); +} diff --git a/app/src/main/java/org/autojs/autojs/model/explorer/ExplorerPage.java b/app/src/main/java/org/autojs/autojs/model/explorer/ExplorerPage.java new file mode 100644 index 00000000..4cd5796d --- /dev/null +++ b/app/src/main/java/org/autojs/autojs/model/explorer/ExplorerPage.java @@ -0,0 +1,17 @@ +package org.autojs.autojs.model.explorer; + +import java.util.ArrayList; +import java.util.Collections; + +public interface ExplorerPage extends ExplorerItem, Iterable { + + void copyChildren(ExplorerPage page); + + boolean updateChild(ExplorerItem oldItem, ExplorerItem newItem); + + boolean removeChild(ExplorerItem item); + + void addChild(ExplorerItem item); + + +} diff --git a/app/src/main/java/org/autojs/autojs/model/explorer/ExplorerProvider.java b/app/src/main/java/org/autojs/autojs/model/explorer/ExplorerProvider.java new file mode 100644 index 00000000..3af3f5ce --- /dev/null +++ b/app/src/main/java/org/autojs/autojs/model/explorer/ExplorerProvider.java @@ -0,0 +1,8 @@ +package org.autojs.autojs.model.explorer; + +import io.reactivex.Single; + +public interface ExplorerProvider { + + Single getExplorerPage(ExplorerPage parent); +} diff --git a/app/src/main/java/org/autojs/autojs/model/explorer/ExplorerSamplePage.java b/app/src/main/java/org/autojs/autojs/model/explorer/ExplorerSamplePage.java new file mode 100644 index 00000000..2d466fac --- /dev/null +++ b/app/src/main/java/org/autojs/autojs/model/explorer/ExplorerSamplePage.java @@ -0,0 +1,33 @@ +package org.autojs.autojs.model.explorer; + +import com.stardust.pio.PFile; + +import java.io.File; + +public class ExplorerSamplePage extends ExplorerDirPage { + + private boolean mRoot = false; + + public ExplorerSamplePage(PFile file, ExplorerPage parent) { + super(file, parent); + } + + public ExplorerSamplePage(String path, ExplorerPage parent) { + super(path, parent); + } + + public ExplorerSamplePage(File file, ExplorerPage parent) { + super(file, parent); + } + + public boolean isRoot() { + return mRoot; + } + + public static ExplorerSamplePage createRoot(PFile dir) { + ExplorerSamplePage page = new ExplorerSamplePage(dir, null); + page.mRoot = true; + return page; + } + +} diff --git a/app/src/main/java/org/autojs/autojs/model/explorer/ExplorerSorter.java b/app/src/main/java/org/autojs/autojs/model/explorer/ExplorerSorter.java new file mode 100644 index 00000000..88896e3e --- /dev/null +++ b/app/src/main/java/org/autojs/autojs/model/explorer/ExplorerSorter.java @@ -0,0 +1,44 @@ +package org.autojs.autojs.model.explorer; + +import java.text.Collator; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +public class ExplorerSorter { + + private static final Collator collator = Collator.getInstance(); + + public static final Comparator NAME = (o1, o2) -> collator.compare(o2.getName(), o1.getName()); + + public static final Comparator DATE = (o1, o2) -> Long.compare(o1.lastModified(), o2.lastModified()); + + public static final Comparator TYPE = (o1, o2) -> o2.getType().compareTo(o1.getType()); + + public static final Comparator SIZE = (o1, o2) -> Long.compare(o2.getSize(), o1.getSize()); + + public static void sort(ExplorerItem[] items, final Comparator comparator, boolean ascending) { + if (ascending) { + Arrays.sort(items, comparator); + } else { + Arrays.sort(items, (o1, o2) -> comparator.compare(o2, o1)); + } + } + + public static void sort(ExplorerItem[] items, Comparator comparator) { + sort(items, comparator, true); + } + + public static void sort(List items, final Comparator comparator, boolean ascending) { + if (ascending) { + Collections.sort(items, comparator); + } else { + Collections.sort(items, (Comparator) (o1, o2) -> comparator.compare(o2, o1)); + } + } + + public static void sort(List items, Comparator comparator) { + sort(items, comparator, true); + } +} diff --git a/app/src/main/java/org/autojs/autojs/model/explorer/Explorers.java b/app/src/main/java/org/autojs/autojs/model/explorer/Explorers.java new file mode 100644 index 00000000..b3dd18dd --- /dev/null +++ b/app/src/main/java/org/autojs/autojs/model/explorer/Explorers.java @@ -0,0 +1,21 @@ +package org.autojs.autojs.model.explorer; + +import com.stardust.app.GlobalAppContext; + +import org.greenrobot.eventbus.EventBus; + +public class Explorers { + + + private static Explorer sWorkspaceExplorer = new Explorer(new WorkspaceFileProvider(GlobalAppContext.get(), null), 20); + + private static Explorer sExternalExplorer = new Explorer(new ExplorerFileProvider(), 10); + + public static Explorer workspace() { + return sWorkspaceExplorer; + } + + public static Explorer external() { + return sExternalExplorer; + } +} diff --git a/app/src/main/java/org/autojs/autojs/model/explorer/WorkspaceFileProvider.java b/app/src/main/java/org/autojs/autojs/model/explorer/WorkspaceFileProvider.java new file mode 100644 index 00000000..e5da7ab3 --- /dev/null +++ b/app/src/main/java/org/autojs/autojs/model/explorer/WorkspaceFileProvider.java @@ -0,0 +1,95 @@ +package org.autojs.autojs.model.explorer; + +import android.content.Context; +import android.content.res.AssetManager; + +import com.stardust.pio.PFile; +import com.stardust.pio.PFiles; + +import org.autojs.autojs.Pref; + +import java.io.File; +import java.io.FileFilter; +import java.io.FileNotFoundException; +import java.io.InputStream; + +import io.reactivex.Observable; +import io.reactivex.Single; +import io.reactivex.schedulers.Schedulers; + +public class WorkspaceFileProvider extends ExplorerFileProvider { + + private static final String SAMPLE_PATH = "sample"; + + private final PFile mSampleDir; + private final AssetManager mAssetManager; + private final Context mContext; + + public WorkspaceFileProvider(Context context, FileFilter fileFilter) { + super(fileFilter); + mContext = context; + mAssetManager = context.getAssets(); + mSampleDir = new PFile(context.getFilesDir(), SAMPLE_PATH); + } + + @Override + public Single getExplorerPage(ExplorerPage page) { + ExplorerPage parent = page.getParent(); + String path = page.getPath(); + return listFiles(new PFile(path)) + .collectInto(createExplorerPage(path, parent), (p, file) -> { + if(file.isDirectory()){ + if(file.getPath().startsWith(mSampleDir.getPath())){ + p.addChild(new ExplorerSamplePage(file, p)); + }else { + p.addChild(new ExplorerDirPage(file, p)); + } + }else { + p.addChild(new ExplorerFileItem(file, p)); + } + }) + .subscribeOn(Schedulers.io()); + } + + @Override + protected Observable listFiles(PFile directory) { + if (directory.getPath().startsWith(mSampleDir.getPath())) { + return listSamples(directory); + } + return super.listFiles(directory); + } + + private Observable listSamples(PFile directory) { + String pathOfSample; + if(directory.getPath().length() <= mSampleDir.getPath().length() + 1){ + pathOfSample = ""; + }else { + pathOfSample = directory.getPath().substring(mSampleDir.getPath().length()); + } + String pathOfAsset = SAMPLE_PATH + pathOfSample; + return Observable.just(pathOfAsset) + .flatMap(path -> Observable.fromArray(mAssetManager.list(path))) + .map(child -> { + PFile file = new PFile(new File(directory, child).getPath()); + if(file.exists()){ + return file; + } + try { + InputStream stream = mAssetManager.open(pathOfAsset + "/" + child); + PFiles.copyStream(stream, file.getPath()); + }catch (FileNotFoundException e){ + file.mkdirs(); + } + return file; + }); + } + + @Override + protected ExplorerDirPage createExplorerPage(String path, ExplorerPage parent) { + ExplorerDirPage page = super.createExplorerPage(path, parent); + if (new File(path).equals(new File(Pref.getScriptDirPath()))) { + page.addChild( ExplorerSamplePage.createRoot(mSampleDir)); + } + return page; + } +} diff --git a/app/src/main/java/org/autojs/autojs/model/script/Scripts.java b/app/src/main/java/org/autojs/autojs/model/script/Scripts.java index 7c213b05..af63d857 100644 --- a/app/src/main/java/org/autojs/autojs/model/script/Scripts.java +++ b/app/src/main/java/org/autojs/autojs/model/script/Scripts.java @@ -12,17 +12,18 @@ import com.stardust.autojs.execution.SimpleScriptExecutionListener; import com.stardust.autojs.runtime.exception.ScriptInterruptedException; import com.stardust.autojs.script.ScriptSource; +import org.autojs.autojs.Pref; import org.autojs.autojs.R; import org.autojs.autojs.autojs.AutoJs; import org.autojs.autojs.external.ScriptIntents; import org.autojs.autojs.external.shortcut.Shortcut; import org.autojs.autojs.external.shortcut.ShortcutActivity; -import org.autojs.autojs.storage.file.StorageFileProvider; import org.autojs.autojs.ui.edit.EditActivity; import org.mozilla.javascript.RhinoException; import java.io.File; +import java.io.FileFilter; /** * Created by Stardust on 2017/5/3. @@ -35,6 +36,9 @@ public class Scripts { public static final String EXTRA_EXCEPTION_LINE_NUMBER = "lineNumber"; public static final String EXTRA_EXCEPTION_COLUMN_NUMBER = "columnNumber"; + public static final FileFilter FILE_FILTER = file -> + file.isDirectory() || file.getName().endsWith(".js") || file.getName().endsWith(".auto"); + private static final ScriptExecutionListener BROADCAST_SENDER_SCRIPT_EXECUTION_LISTENER = new SimpleScriptExecutionListener() { @Override @@ -99,8 +103,8 @@ public class Scripts { public static ScriptExecution run(ScriptSource source) { return AutoJs.getInstance().getScriptEngineService().execute(source, new ExecutionConfig() - .executePath(StorageFileProvider.getDefaultDirectoryPath()) - .requirePath(StorageFileProvider.getDefaultDirectoryPath())); + .executePath(Pref.getScriptDirPath()) + .requirePath(Pref.getScriptDirPath())); } public static ScriptExecution runWithBroadcastSender(File file) { diff --git a/app/src/main/java/org/autojs/autojs/pluginclient/DevPluginResponseHandler.java b/app/src/main/java/org/autojs/autojs/pluginclient/DevPluginResponseHandler.java index 93469521..23d72f00 100644 --- a/app/src/main/java/org/autojs/autojs/pluginclient/DevPluginResponseHandler.java +++ b/app/src/main/java/org/autojs/autojs/pluginclient/DevPluginResponseHandler.java @@ -10,10 +10,10 @@ import com.stardust.autojs.execution.ScriptExecution; import com.stardust.autojs.script.StringScriptSource; import com.stardust.pio.PFiles; +import org.autojs.autojs.Pref; import org.autojs.autojs.R; import org.autojs.autojs.autojs.AutoJs; import org.autojs.autojs.model.script.Scripts; -import org.autojs.autojs.storage.file.StorageFileProvider; import java.io.File; import java.util.HashMap; @@ -99,7 +99,7 @@ public class DevPluginResponseHandler implements Handler { if (!name.endsWith(".js")) { name = name + ".js"; } - PFiles.write(new File(StorageFileProvider.getDefaultDirectoryPath(), name), script); + PFiles.write(new File(Pref.getScriptDirPath(), name), script); GlobalAppContext.toast(R.string.text_script_save_successfully); } } diff --git a/app/src/main/java/org/autojs/autojs/storage/file/SampleFileProvider.java b/app/src/main/java/org/autojs/autojs/storage/file/SampleFileProvider.java deleted file mode 100644 index fc0818d9..00000000 --- a/app/src/main/java/org/autojs/autojs/storage/file/SampleFileProvider.java +++ /dev/null @@ -1,74 +0,0 @@ -package org.autojs.autojs.storage.file; - -import android.content.Context; -import android.content.res.AssetManager; -import android.support.annotation.NonNull; - -import com.stardust.pio.PFile; -import com.stardust.pio.PFiles; -import org.autojs.autojs.model.script.ScriptFile; - -import java.io.File; - -import io.reactivex.Observable; - -/** - * Created by Stardust on 2017/10/28. - */ - -public class SampleFileProvider extends StorageFileProvider { - - private AssetManager mAssetManager; - private Context mContext; - - public SampleFileProvider(String path, Context context) { - super(path, 10); - mContext = context; - mAssetManager = context.getAssets(); - } - - public SampleFileProvider(Context context) { - this("sample/", context); - } - - @Override - protected Observable listFiles(PFile directory) { - return Observable.just(directory) - .flatMap(dir -> Observable.fromArray(mAssetManager.list(directory.getPath()))) - .map(path -> { - String absPath = new File(directory, path).getPath(); - if (!absPath.endsWith(".js")) { - return new AssetDirectory(absPath); - } - PFile file = new PFile(mContext.getFilesDir(), absPath); - if (!file.exists()) { - copySample(mContext, absPath, file.getPath()); - } - return file; - }); - - } - - public static boolean copySample(Context context, String samplePath, String pathTo) { - PFiles.ensureDir(pathTo); - return PFiles.copyAsset(context, samplePath, pathTo); - } - - public static class AssetDirectory extends ScriptFile { - - public AssetDirectory(@NonNull String pathname) { - super(pathname); - } - - @Override - public boolean isDirectory() { - return true; - } - - @Override - public boolean isFile() { - return false; - } - } - -} diff --git a/app/src/main/java/org/autojs/autojs/storage/file/StorageFileProvider.java b/app/src/main/java/org/autojs/autojs/storage/file/StorageFileProvider.java deleted file mode 100644 index e66a906f..00000000 --- a/app/src/main/java/org/autojs/autojs/storage/file/StorageFileProvider.java +++ /dev/null @@ -1,231 +0,0 @@ -package org.autojs.autojs.storage.file; - -import android.os.Environment; - -import com.stardust.app.GlobalAppContext; -import com.stardust.pio.PFile; - -import org.autojs.autojs.Pref; -import org.autojs.autojs.R; - -import com.stardust.util.LimitedHashMap; - -import org.greenrobot.eventbus.EventBus; - -import java.io.FileFilter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -import io.reactivex.Observable; - -/** - * Created by Stardust on 2017/3/31. - */ - -public class StorageFileProvider { - - public static final int REMOVE = 0; - public static final int CREATE = 1; - public static final int CHANGE = 2; - public static final int ALL = 3; - - public static final FileFilter SCRIPT_FILTER = file -> - file.isDirectory() || file.getName().endsWith(".js") || file.getName().endsWith(".auto"); - - public static class DirectoryChangeEvent { - - - private final PFile mDir; - private final int mChange; - private final PFile mFile; - private final PFile mNewFile; - - public DirectoryChangeEvent(PFile dir, int change, PFile file) { - this(dir, change, file, file); - } - - public DirectoryChangeEvent(PFile directory) { - this(directory, ALL, null); - } - - public DirectoryChangeEvent(PFile dir, int change, PFile oldFile, PFile newFile) { - mDir = dir; - mChange = change; - mFile = oldFile; - mNewFile = newFile; - } - - public PFile getDir() { - return mDir; - } - - public int getChange() { - return mChange; - } - - public PFile getFile() { - return mFile; - } - - public PFile getNewFile() { - return mNewFile; - } - } - - - private static final PFile INITIAL_DIRECTORY_DEFAULT = new PFile(""); - - private static StorageFileProvider externalStorageProvider; - private static final StorageFileProvider DEFAULT_PROVIDER = new StorageFileProvider(INITIAL_DIRECTORY_DEFAULT, 10, SCRIPT_FILTER); - - private EventBus mDirectoryEventBus = new EventBus(); - private LimitedHashMap> mPFileCache; - private PFile mInitialDirectory; - private FileFilter mFileFilter; - - public StorageFileProvider(PFile initialDirectory, int cacheSize, FileFilter fileFilter) { - mInitialDirectory = initialDirectory; - mFileFilter = fileFilter; - mPFileCache = new LimitedHashMap<>(cacheSize); - } - - - public StorageFileProvider(String path, int cacheSize) { - this(new PFile(path), cacheSize); - } - - public StorageFileProvider(PFile initialDirectory, int cacheSize) { - mInitialDirectory = initialDirectory; - mPFileCache = new LimitedHashMap<>(cacheSize); - } - - public StorageFileProvider() { - this(getDefaultDirectory(), 10); - } - - public static String getDefaultDirectoryPath() { - return getDefaultDirectory().getPath(); - } - - public static PFile getDefaultDirectory() { - return new PFile(Environment.getExternalStorageDirectory(), Pref.getScriptDirPath()); - } - - public static StorageFileProvider getDefault() { - return DEFAULT_PROVIDER; - } - - public static StorageFileProvider getExternalStorageProvider() { - if (externalStorageProvider == null) { - externalStorageProvider = new StorageFileProvider(Environment.getExternalStorageDirectory().getPath(), 5); - } - return externalStorageProvider; - } - - public void notifyDirectoryChanged(PFile directory) { - clearCache(directory); - mDirectoryEventBus.post(new DirectoryChangeEvent(directory)); - } - - public void notifyFileChanged(PFile dir, PFile oldFile, PFile newFile) { - List files = getFilesFromCache(dir); - if (files == null) - return; - int i = files.indexOf(oldFile); - if (i >= 0) { - files.set(i, newFile); - mDirectoryEventBus.post(new DirectoryChangeEvent(dir, CHANGE, oldFile, newFile)); - } - } - - - public void notifyFileRemoved(PFile dir, PFile file) { - List files = getFilesFromCache(dir); - if (files == null) - return; - if (files.remove(file)) { - mDirectoryEventBus.post(new DirectoryChangeEvent(dir, REMOVE, file)); - } - } - - public void notifyFileCreated(PFile dir, PFile file) { - List files = getFilesFromCache(dir); - if (files == null) - return; - files.add(0, file); - mDirectoryEventBus.post(new DirectoryChangeEvent(dir, CREATE, file)); - } - - public void notifyStoragePermissionGranted() { - mPFileCache.clear(); - mDirectoryEventBus.post(new DirectoryChangeEvent(getInitialDirectory())); - } - - @SuppressWarnings("unchecked") - public void refreshAll() { - Map files = (Map) mPFileCache.clone(); - mPFileCache.clear(); - mDirectoryEventBus.post(new DirectoryChangeEvent(getInitialDirectory())); - for (Map.Entry file : files.entrySet()) { - mDirectoryEventBus.post(new DirectoryChangeEvent(new PFile(file.getKey()))); - } - } - - public PFile getInitialDirectory() { - if (mInitialDirectory == INITIAL_DIRECTORY_DEFAULT) { - return getDefaultDirectory(); - } - return mInitialDirectory; - } - - public Observable getInitialDirectoryFiles() { - return getDirectoryFiles(getInitialDirectory()); - } - - public Observable getDirectoryFiles(PFile directory) { - List PFiles = getFilesFromCache(directory); - if (PFiles == null) { - return listFiles(directory); - } - return Observable.fromIterable(PFiles); - } - - private void clearCache(PFile directory) { - mPFileCache.remove(directory.getPath()); - } - - - protected Observable listFiles(PFile directory) { - return Observable.just(directory) - .flatMap(dir -> { - PFile[] files; - if (mFileFilter == null) { - files = dir.listFiles(); - } else { - files = dir.listFiles(mFileFilter); - } - if (files == null) { - return Observable.empty(); - } - mPFileCache.put(dir.getPath(), new ArrayList<>(Arrays.asList(files))); - return Observable.fromArray(files); - }); - } - - private List getFilesFromCache(PFile directory) { - return mPFileCache.get(directory.getPath()); - } - - - public void registerDirectoryChangeListener(Object subscriber) { - if (!mDirectoryEventBus.isRegistered(subscriber)) - mDirectoryEventBus.register(subscriber); - } - - public void unregisterDirectoryChangeListener(Object subscriber) { - mDirectoryEventBus.unregister(subscriber); - } - -} diff --git a/app/src/main/java/org/autojs/autojs/timing/TimedTaskManager.java b/app/src/main/java/org/autojs/autojs/timing/TimedTaskManager.java index 021488e9..9640c9e3 100644 --- a/app/src/main/java/org/autojs/autojs/timing/TimedTaskManager.java +++ b/app/src/main/java/org/autojs/autojs/timing/TimedTaskManager.java @@ -14,8 +14,8 @@ import com.raizlabs.android.dbflow.structure.BaseModel; import com.raizlabs.android.dbflow.structure.ModelAdapter; import com.stardust.app.GlobalAppContext; +import org.autojs.autojs.Pref; import org.autojs.autojs.storage.database.ModelChange; -import org.autojs.autojs.storage.file.StorageFileProvider; import java.io.File; import java.util.List; @@ -106,7 +106,7 @@ public class TimedTaskManager { public Flowable getIntentTaskOfAction(String action) { IntentTask intentTask = new IntentTask(); intentTask.setAction(Intent.ACTION_BOOT_COMPLETED); - intentTask.setScriptPath(new File(StorageFileProvider.getDefaultDirectory(), "boot.js").getPath()); + intentTask.setScriptPath(new File(Pref.getScriptDirPath(), "boot.js").getPath()); return Flowable.just(intentTask); // return RXSQLite.rx(SQLite.select().from(IntentTask.class)) // .queryStreamResults() diff --git a/app/src/main/java/org/autojs/autojs/ui/build/BuildActivity.java b/app/src/main/java/org/autojs/autojs/ui/build/BuildActivity.java index 4cd53fb2..b7039d94 100644 --- a/app/src/main/java/org/autojs/autojs/ui/build/BuildActivity.java +++ b/app/src/main/java/org/autojs/autojs/ui/build/BuildActivity.java @@ -23,11 +23,11 @@ import org.androidannotations.annotations.AfterViews; import org.androidannotations.annotations.Click; import org.androidannotations.annotations.EActivity; import org.androidannotations.annotations.ViewById; +import org.autojs.autojs.Pref; import org.autojs.autojs.R; import org.autojs.autojs.autojs.build.AutoJsApkBuilder; import org.autojs.autojs.build.ApkBuilderPluginHelper; import org.autojs.autojs.model.script.ScriptFile; -import org.autojs.autojs.storage.file.StorageFileProvider; import org.autojs.autojs.theme.dialog.ThemeColorMaterialDialogBuilder; import org.autojs.autojs.tool.BitmapTool; import org.autojs.autojs.ui.BaseActivity; @@ -136,7 +136,7 @@ public class BuildActivity extends BaseActivity implements AutoJsApkBuilder.Prog private void setupWithSourceFile(ScriptFile file) { String dir = file.getParent(); if (dir.startsWith(getFilesDir().getPath())) { - dir = StorageFileProvider.getDefaultDirectoryPath(); + dir = Pref.getScriptDirPath(); } mOutputPath.setText(dir); mAppName.setText(file.getSimplifiedName()); @@ -156,7 +156,7 @@ public class BuildActivity extends BaseActivity implements AutoJsApkBuilder.Prog new FileChooserDialogBuilder(this) .title(R.string.text_source_file_path) .dir(Environment.getExternalStorageDirectory().getPath(), - initialDir == null ? StorageFileProvider.getDefaultDirectoryPath() : initialDir) + initialDir == null ? Pref.getScriptDirPath() : initialDir) .singleChoice(this::setSource) .show(); } @@ -178,7 +178,7 @@ public class BuildActivity extends BaseActivity implements AutoJsApkBuilder.Prog @Click(R.id.select_output) void selectOutputDirPath() { String initialDir = new File(mOutputPath.getText().toString()).exists() ? - mOutputPath.getText().toString() : StorageFileProvider.getDefaultDirectoryPath(); + mOutputPath.getText().toString() : Pref.getScriptDirPath(); new FileChooserDialogBuilder(this) .title(R.string.text_output_apk_path) .dir(initialDir) diff --git a/app/src/main/java/org/autojs/autojs/ui/common/ScriptOperations.java b/app/src/main/java/org/autojs/autojs/ui/common/ScriptOperations.java index 7e927258..793dc738 100644 --- a/app/src/main/java/org/autojs/autojs/ui/common/ScriptOperations.java +++ b/app/src/main/java/org/autojs/autojs/ui/common/ScriptOperations.java @@ -9,7 +9,6 @@ import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.design.widget.Snackbar; import android.text.InputType; -import android.util.Log; import android.view.View; import android.widget.EditText; import android.widget.Toast; @@ -22,22 +21,24 @@ import com.stardust.pio.PFile; import com.stardust.pio.PFiles; import com.stardust.pio.UncheckedIOException; +import org.autojs.autojs.Pref; import org.autojs.autojs.R; import org.autojs.autojs.external.ScriptIntents; +import org.autojs.autojs.model.explorer.Explorer; +import org.autojs.autojs.model.explorer.ExplorerFileItem; +import org.autojs.autojs.model.explorer.ExplorerItem; +import org.autojs.autojs.model.explorer.Explorers; import org.autojs.autojs.storage.file.TmpScriptFiles; import org.autojs.autojs.model.sample.SampleFile; import org.autojs.autojs.model.script.ScriptFile; import org.autojs.autojs.model.script.Scripts; -import org.autojs.autojs.storage.file.StorageFileProvider; import org.autojs.autojs.network.download.DownloadManager; -import org.autojs.autojs.tool.SimpleObserver; import org.autojs.autojs.ui.filechooser.FileChooserDialogBuilder; import org.autojs.autojs.ui.shortcut.ShortcutCreateActivity; import org.autojs.autojs.ui.timing.TimedTaskSettingActivity_; import org.autojs.autojs.theme.dialog.ThemeColorMaterialDialogBuilder; import org.reactivestreams.Publisher; -import org.reactivestreams.Subscriber; import java.io.File; import java.io.IOException; @@ -53,23 +54,34 @@ import io.reactivex.subjects.PublishSubject; * Created by Stardust on 2017/7/31. */ +@SuppressLint("CheckResult") public class ScriptOperations { private static final String LOG_TAG = "ScriptOperations"; + private final ExplorerItem mExplorerItem; private Context mContext; private View mView; private ScriptFile mCurrentDirectory; - private StorageFileProvider mStorageFileProvider; + private Explorer mExplorer; public ScriptOperations(Context context, View view, ScriptFile currentDirectory) { mContext = context; mView = view; mCurrentDirectory = currentDirectory; - mStorageFileProvider = StorageFileProvider.getDefault(); + mExplorer = Explorers.workspace(); + mExplorerItem = new ExplorerFileItem(currentDirectory, null); + } + + public ScriptOperations(Context context, View view, ExplorerItem item) { + mContext = context; + mView = view; + mCurrentDirectory = item.toScriptFile(); + mExplorer = Explorers.workspace(); + mExplorerItem = item; } public ScriptOperations(Context context, View view) { - this(context, view, new ScriptFile(StorageFileProvider.getDefaultDirectory())); + this(context, view, new ScriptFile(Pref.getScriptDirPath())); } public void newScriptFileForScript(final String script) { @@ -97,7 +109,7 @@ public class ScriptOperations { return; } } - mStorageFileProvider.notifyFileCreated(mCurrentDirectory, new ScriptFile(path)); + notifyFileCreated(mCurrentDirectory, new ScriptFile(path)); if (edit) Scripts.edit(path); } else { @@ -105,6 +117,10 @@ public class ScriptOperations { } } + private void notifyFileCreated(ScriptFile directory, ScriptFile scriptFile) { + mExplorer.notifyItemCreated(new ExplorerFileItem(scriptFile, mExplorerItem.getParent())); + } + public void newScriptFile() { showFileNameInputDialog("", "js") .subscribe(input -> createScriptFile(getCurrentDirectoryPath() + input + ".js", null, true)); @@ -123,7 +139,7 @@ public class ScriptOperations { return pathTo; }) .observeOn(AndroidSchedulers.mainThread()) - .doOnNext(path -> mStorageFileProvider.notifyFileCreated(mCurrentDirectory, new ScriptFile(path))); + .doOnNext(path -> notifyFileCreated(mCurrentDirectory, new ScriptFile(path))); } public Observable importFile(String prefix, final InputStream inputStream, final String ext) { @@ -136,7 +152,7 @@ public class ScriptOperations { } else { showMessage(R.string.text_import_fail); } - mStorageFileProvider.notifyFileCreated(mCurrentDirectory, new ScriptFile(pathTo)); + notifyFileCreated(mCurrentDirectory, new ScriptFile(pathTo)); return pathTo; }); } @@ -148,7 +164,7 @@ public class ScriptOperations { ScriptFile newDir = new ScriptFile(getCurrentDirectory(), path); if (newDir.mkdirs()) { showMessage(R.string.text_already_create); - mStorageFileProvider.notifyFileCreated(mCurrentDirectory, new ScriptFile(newDir)); + notifyFileCreated(mCurrentDirectory, new ScriptFile(newDir)); } else { showMessage(R.string.text_create_fail); } @@ -213,12 +229,17 @@ public class ScriptOperations { .map(newName -> { PFile newFile = file.renameAndReturnNewFile(newName); if (newFile != null) { - mStorageFileProvider.notifyFileChanged(mCurrentDirectory, oldFile, newFile); + notifyFileChanged(mCurrentDirectory, oldFile, newFile); } return newFile != null; }); } + private void notifyFileChanged(ScriptFile directory, ScriptFile oldFile, PFile newFile) { + mExplorer.notifyItemChanged(new ExplorerFileItem(oldFile, mExplorerItem.getParent()), + new ExplorerFileItem(newFile, mExplorerItem.getParent())); + } + public void createShortcut(ScriptFile file) { mContext.startActivity(new Intent(mContext, ShortcutCreateActivity.class) .putExtra(ShortcutCreateActivity.EXTRA_FILE, file)); @@ -244,10 +265,14 @@ public class ScriptOperations { .subscribe(deleted -> { showMessage(deleted ? R.string.text_already_delete : R.string.text_delete_failed); if (deleted) - mStorageFileProvider.notifyFileRemoved(mCurrentDirectory, scriptFile); + notifyFileRemoved(mCurrentDirectory, scriptFile); }); } + private void notifyFileRemoved(ScriptFile directory, ScriptFile scriptFile) { + mExplorer.notifyItemRemoved(new ExplorerFileItem(scriptFile, mExplorerItem.getParent())); + } + public Observable download(String url) { String fileName = DownloadManager.parseFileNameLocally(url); diff --git a/app/src/main/java/org/autojs/autojs/ui/explorer/ExplorerViewHelper.java b/app/src/main/java/org/autojs/autojs/ui/explorer/ExplorerViewHelper.java new file mode 100644 index 00000000..1b1f11cc --- /dev/null +++ b/app/src/main/java/org/autojs/autojs/ui/explorer/ExplorerViewHelper.java @@ -0,0 +1,67 @@ +package org.autojs.autojs.ui.explorer; + +import android.graphics.Color; + +import com.stardust.app.GlobalAppContext; +import com.stardust.pio.PFiles; + +import org.autojs.autojs.R; +import org.autojs.autojs.model.explorer.ExplorerFileItem; +import org.autojs.autojs.model.explorer.ExplorerItem; +import org.autojs.autojs.model.explorer.ExplorerPage; +import org.autojs.autojs.model.explorer.ExplorerSamplePage; + +import static android.support.v4.content.ContextCompat.getColor; +import static org.autojs.autojs.model.explorer.ExplorerItem.TYPE_AUTO_FILE; +import static org.autojs.autojs.model.explorer.ExplorerItem.TYPE_JAVASCRIPT; +import static org.autojs.autojs.model.explorer.ExplorerItem.TYPE_UNKNOWN; + +public class ExplorerViewHelper { + + public static String getDisplayName(ExplorerItem item) { + if (item instanceof ExplorerSamplePage && ((ExplorerSamplePage) item).isRoot()) { + return GlobalAppContext.getString(R.string.text_sample); + } + if (item instanceof ExplorerPage) { + return item.getName(); + } + String type = item.getType(); + if (type.equals(TYPE_JAVASCRIPT) || type.equals(TYPE_AUTO_FILE)) { + if (item instanceof ExplorerFileItem) { + return ((ExplorerFileItem) item).getFile().getSimplifiedName(); + } + return PFiles.getNameWithoutExtension(item.getName()); + } + return item.getName(); + } + + public static String getIconText(ExplorerItem item) { + String type = item.getType(); + if (type.isEmpty()) { + return TYPE_UNKNOWN; + } + if (type.equals(TYPE_AUTO_FILE)) { + return "R"; + } + + return type.substring(0, 1).toUpperCase(); + } + + public static int getIconColor(ExplorerItem item) { + switch (item.getType()) { + case TYPE_JAVASCRIPT: + return getColor(GlobalAppContext.get(), R.color.color_j); + case TYPE_AUTO_FILE: + return getColor(GlobalAppContext.get(), R.color.color_r); + default: + return Color.GRAY; + } + } + + public static int getIcon(ExplorerPage page) { + if (page instanceof ExplorerSamplePage) { + return R.drawable.ic_sample_dir; + } + return R.drawable.ic_folder_yellow_100px; + } +} diff --git a/app/src/main/java/org/autojs/autojs/ui/filechooser/FileChooseListView.java b/app/src/main/java/org/autojs/autojs/ui/filechooser/FileChooseListView.java index bfbf530f..8afb1fd5 100644 --- a/app/src/main/java/org/autojs/autojs/ui/filechooser/FileChooseListView.java +++ b/app/src/main/java/org/autojs/autojs/ui/filechooser/FileChooseListView.java @@ -3,19 +3,23 @@ package org.autojs.autojs.ui.filechooser; import android.content.Context; import android.graphics.drawable.GradientDrawable; import android.support.annotation.Nullable; -import android.support.v4.content.res.ResourcesCompat; import android.support.v7.widget.SimpleItemAnimator; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.ImageView; import android.widget.TextView; import com.stardust.pio.PFile; import com.stardust.pio.PFiles; + import org.autojs.autojs.R; +import org.autojs.autojs.model.explorer.ExplorerItem; +import org.autojs.autojs.model.explorer.ExplorerPage; import org.autojs.autojs.model.script.ScriptFile; -import org.autojs.autojs.ui.main.scripts.ScriptListView; +import org.autojs.autojs.ui.explorer.ExplorerViewHelper; +import org.autojs.autojs.ui.main.scripts.ExplorerView; import org.autojs.autojs.ui.widget.BindableViewHolder; import org.autojs.autojs.ui.widget.CheckBoxCompat; @@ -33,7 +37,7 @@ import butterknife.OnClick; * Created by Stardust on 2017/10/19. */ -public class FileChooseListView extends ScriptListView { +public class FileChooseListView extends ExplorerView { private int mMaxChoice = 1; private LinkedHashMap mSelectedFiles = new LinkedHashMap<>(); @@ -66,17 +70,16 @@ public class FileChooseListView extends ScriptListView { } private void init() { - setDirectorySpanSize(2); - ((SimpleItemAnimator) getScriptListView().getItemAnimator()) + ((SimpleItemAnimator) getExplorerItemListView().getItemAnimator()) .setSupportsChangeAnimations(false); } @Override protected BindableViewHolder onCreateViewHolder(LayoutInflater inflater, ViewGroup parent, int viewType) { - if (viewType == VIEW_TYPE_FILE) { - return new ScriptFileViewHolder(inflater.inflate(R.layout.file_choose_list_file, parent, false)); - } else if (viewType == VIEW_TYPE_DIRECTORY) { - return new DirectoryViewHolder(inflater.inflate(R.layout.file_choose_list_directory, parent, false)); + if (viewType == VIEW_TYPE_ITEM) { + return new ExplorerItemViewHolder(inflater.inflate(R.layout.file_choose_list_file, parent, false)); + } else if (viewType == VIEW_TYPE_PAGE) { + return new ExplorerPageViewHolder(inflater.inflate(R.layout.file_choose_list_directory, parent, false)); } else { return super.onCreateViewHolder(inflater, parent, viewType); } @@ -87,13 +90,13 @@ public class FileChooseListView extends ScriptListView { Map.Entry itemToUncheck = mSelectedFiles.entrySet().iterator().next(); int positionOfItemToUncheck = itemToUncheck.getValue(); mSelectedFiles.remove(itemToUncheck.getKey()); - getScriptListView().getAdapter().notifyItemChanged(positionOfItemToUncheck); + getExplorerItemListView().getAdapter().notifyItemChanged(positionOfItemToUncheck); } mSelectedFiles.put(file, position); } - class ScriptFileViewHolder extends BindableViewHolder { + class ExplorerItemViewHolder extends BindableViewHolder { @BindView(R.id.name) TextView mName; @@ -105,27 +108,22 @@ public class FileChooseListView extends ScriptListView { TextView mDesc; GradientDrawable mFirstCharBackground; - private ScriptFile mScriptFile; + private ExplorerItem mExplorerItem; - ScriptFileViewHolder(View itemView) { + ExplorerItemViewHolder(View itemView) { super(itemView); ButterKnife.bind(this, itemView); mFirstCharBackground = (GradientDrawable) mFirstChar.getBackground(); } @Override - public void bind(ScriptFile file, int position) { - mScriptFile = file; - mName.setText(file.getSimplifiedName()); - mDesc.setText(PFiles.getHumanReadableSize(file.length())); - mCheckBox.setChecked(mSelectedFiles.containsKey(file), false); - if (file.getType() == ScriptFile.TYPE_JAVA_SCRIPT) { - mFirstChar.setText("J"); - mFirstCharBackground.setColor(ResourcesCompat.getColor(getResources(), R.color.color_j, getContext().getTheme())); - } else { - mFirstChar.setText("R"); - mFirstCharBackground.setColor(ResourcesCompat.getColor(getResources(), R.color.color_r, getContext().getTheme())); - } + public void bind(ExplorerItem item, int position) { + mExplorerItem = item; + mName.setText(ExplorerViewHelper.getDisplayName(item)); + mDesc.setText(PFiles.getHumanReadableSize(item.getSize())); + mFirstChar.setText(ExplorerViewHelper.getIconText(item)); + mFirstCharBackground.setColor(ExplorerViewHelper.getIconColor(item)); + mCheckBox.setChecked(mSelectedFiles.containsKey(mExplorerItem.toScriptFile()), false); } @OnClick(R.id.item) @@ -136,16 +134,16 @@ public class FileChooseListView extends ScriptListView { @OnCheckedChanged(R.id.checkbox) void onCheckedChanged() { if (mCheckBox.isChecked()) { - check(mScriptFile, getAdapterPosition()); + check(mExplorerItem.toScriptFile(), getAdapterPosition()); } else { - mSelectedFiles.remove(mScriptFile); + mSelectedFiles.remove(mExplorerItem.toScriptFile()); } } } - class DirectoryViewHolder extends BindableViewHolder { + class ExplorerPageViewHolder extends BindableViewHolder { @BindView(R.id.name) TextView mName; @@ -153,34 +151,38 @@ public class FileChooseListView extends ScriptListView { @BindView(R.id.checkbox) CheckBoxCompat mCheckBox; - private ScriptFile mScriptFile; + @BindView(R.id.icon) + ImageView mIcon; - DirectoryViewHolder(View itemView) { + private ExplorerPage mExplorerPage; + + ExplorerPageViewHolder(View itemView) { super(itemView); ButterKnife.bind(this, itemView); mCheckBox.setVisibility(mCanChooseDir ? VISIBLE : GONE); } @Override - public void bind(ScriptFile data, int position) { - mName.setText(data.getSimplifiedName()); - mScriptFile = data; + public void bind(ExplorerPage data, int position) { + mExplorerPage = data; + mName.setText(ExplorerViewHelper.getDisplayName(data)); + mIcon.setImageResource(ExplorerViewHelper.getIcon(data)); if (mCanChooseDir) { - mCheckBox.setChecked(mSelectedFiles.containsKey(data), false); + mCheckBox.setChecked(mSelectedFiles.containsKey(data.toScriptFile()), false); } } @OnClick(R.id.item) void onItemClick() { - setCurrentDirectory(mScriptFile); + enterChildPage(mExplorerPage); } @OnCheckedChanged(R.id.checkbox) void onCheckedChanged() { if (mCheckBox.isChecked()) { - check(mScriptFile, getAdapterPosition()); + check(mExplorerPage.toScriptFile(), getAdapterPosition()); } else { - mSelectedFiles.remove(mScriptFile); + mSelectedFiles.remove(mExplorerPage.toScriptFile()); } } diff --git a/app/src/main/java/org/autojs/autojs/ui/filechooser/FileChooserDialogBuilder.java b/app/src/main/java/org/autojs/autojs/ui/filechooser/FileChooserDialogBuilder.java index d08a5590..7021f7d0 100644 --- a/app/src/main/java/org/autojs/autojs/ui/filechooser/FileChooserDialogBuilder.java +++ b/app/src/main/java/org/autojs/autojs/ui/filechooser/FileChooserDialogBuilder.java @@ -4,13 +4,19 @@ import android.content.Context; import android.support.annotation.NonNull; import android.support.annotation.StringRes; +import com.afollestad.materialdialogs.MaterialDialog; import com.stardust.pio.PFile; + import org.autojs.autojs.R; -import org.autojs.autojs.model.script.ScriptFile; -import org.autojs.autojs.storage.file.StorageFileProvider; +import org.autojs.autojs.model.explorer.Explorer; +import org.autojs.autojs.model.explorer.ExplorerDirPage; +import org.autojs.autojs.model.explorer.ExplorerFileProvider; +import org.autojs.autojs.model.explorer.Explorers; +import org.autojs.autojs.model.script.Scripts; import org.autojs.autojs.theme.dialog.ThemeColorMaterialDialogBuilder; import java.io.File; +import java.io.FileFilter; import java.util.Collections; import java.util.List; @@ -32,8 +38,10 @@ public class FileChooserDialogBuilder extends ThemeColorMaterialDialogBuilder { } private FileChooseListView mFileChooseListView; - private PFile mRootDir = StorageFileProvider.getDefaultDirectory(); private MultiChoiceCallback mCallback; + private FileFilter mFileFilter; + private String mRootDir; + private String mInitialDir; public FileChooserDialogBuilder(@NonNull Context context) { super(context); @@ -41,9 +49,7 @@ public class FileChooserDialogBuilder extends ThemeColorMaterialDialogBuilder { customView(mFileChooseListView, false); positiveText(R.string.ok); negativeText(R.string.cancel); - onPositive((dialog, which) -> { - notifySelected(); - }); + onPositive((dialog, which) -> notifySelected()); } private void notifySelected() { @@ -58,28 +64,26 @@ public class FileChooserDialogBuilder extends ThemeColorMaterialDialogBuilder { } public FileChooserDialogBuilder dir(String rootDir, String initialDir) { - mRootDir = new PFile(rootDir); - if (mRootDir.equals(StorageFileProvider.getDefaultDirectory())) { - mFileChooseListView.setStorageFileProvider(StorageFileProvider.getDefault()); - } else { - mFileChooseListView.setStorageFileProvider(new StorageFileProvider(mRootDir, 10), new ScriptFile(initialDir)); - } + mRootDir = rootDir; + mInitialDir = initialDir; + return this; } public FileChooserDialogBuilder dir(String dir) { - return dir(dir, dir); + mRootDir = dir; + return this; } public FileChooserDialogBuilder justScriptFile() { - mFileChooseListView.setStorageFileProvider(new StorageFileProvider(mRootDir, 10, StorageFileProvider.SCRIPT_FILTER)); + mFileFilter = Scripts.FILE_FILTER; return this; } public FileChooserDialogBuilder chooseDir() { + mFileFilter = File::isDirectory; mFileChooseListView.setCanChooseDir(true); - mFileChooseListView.setStorageFileProvider(new StorageFileProvider(mRootDir, 10, File::isDirectory)); return this; } @@ -121,4 +125,18 @@ public class FileChooserDialogBuilder extends ThemeColorMaterialDialogBuilder { super.title(titleRes); return this; } + + @Override + public MaterialDialog build() { + ExplorerDirPage root = ExplorerDirPage.createRoot(mRootDir); + Explorer explorer = mFileFilter == null ? Explorers.external() : + new Explorer(new ExplorerFileProvider(mFileFilter), 0); + if(mInitialDir == null){ + mFileChooseListView.setExplorer(explorer, root); + }else { + mFileChooseListView.setExplorer(explorer, root, + new ExplorerDirPage(mInitialDir, root)); + } + return super.build(); + } } diff --git a/app/src/main/java/org/autojs/autojs/ui/floating/CircularMenu.java b/app/src/main/java/org/autojs/autojs/ui/floating/CircularMenu.java index 67e91a8e..782b155d 100644 --- a/app/src/main/java/org/autojs/autojs/ui/floating/CircularMenu.java +++ b/app/src/main/java/org/autojs/autojs/ui/floating/CircularMenu.java @@ -15,19 +15,22 @@ import com.stardust.autojs.core.record.Recorder; import com.stardust.enhancedfloaty.FloatyService; import com.stardust.enhancedfloaty.FloatyWindow; import com.stardust.floatingcircularactionmenu.CircularActionMenu; + +import org.autojs.autojs.Pref; import org.autojs.autojs.R; import org.autojs.autojs.accessibility.AccessibilityService; import org.autojs.autojs.autojs.AutoJs; import org.autojs.autojs.autojs.record.GlobalActionRecorder; +import org.autojs.autojs.model.explorer.ExplorerDirPage; +import org.autojs.autojs.model.explorer.Explorers; import org.autojs.autojs.model.script.Scripts; -import org.autojs.autojs.storage.file.StorageFileProvider; import org.autojs.autojs.tool.AccessibilityServiceTool; import org.autojs.autojs.tool.RootTool; import org.autojs.autojs.ui.common.NotAskAgainDialog; import org.autojs.autojs.ui.floating.layoutinspector.LayoutBoundsFloatyWindow; import org.autojs.autojs.ui.floating.layoutinspector.LayoutHierarchyFloatyWindow; import org.autojs.autojs.ui.main.MainActivity_; -import org.autojs.autojs.ui.main.scripts.ScriptListView; +import org.autojs.autojs.ui.main.scripts.ExplorerView; import org.autojs.autojs.theme.dialog.ThemeColorMaterialDialogBuilder; import com.stardust.util.ClipboardUtil; import com.stardust.util.Func1; @@ -132,16 +135,16 @@ public class CircularMenu implements Recorder.OnStateChangedListener, LayoutInsp @OnClick(R.id.script_list) void showScriptList() { mWindow.collapse(); - ScriptListView listView = new ScriptListView(mContext); - listView.setStorageFileProvider(StorageFileProvider.getDefault()); - listView.setDirectorySpanSize(2); + ExplorerView explorerView = new ExplorerView(mContext); + explorerView.setExplorer(Explorers.workspace(), ExplorerDirPage.createRoot(Pref.getScriptDirPath())); + explorerView.setDirectorySpanSize(2); final MaterialDialog dialog = new ThemeColorMaterialDialogBuilder(mContext) .title(R.string.text_run_script) - .customView(listView, false) + .customView(explorerView, false) .positiveText(R.string.cancel) .build(); - listView.setOnItemOperatedListener(file -> dialog.dismiss()); - listView.setOnScriptFileClickListener((view, file) -> Scripts.run(file)); + explorerView.setOnItemOperatedListener(file -> dialog.dismiss()); + explorerView.setOnItemClickListener((view, item) -> Scripts.run(item.toScriptFile())); DialogUtils.showDialog(dialog); } diff --git a/app/src/main/java/org/autojs/autojs/ui/main/MainActivity.java b/app/src/main/java/org/autojs/autojs/ui/main/MainActivity.java index cc62050e..3d05c99b 100644 --- a/app/src/main/java/org/autojs/autojs/ui/main/MainActivity.java +++ b/app/src/main/java/org/autojs/autojs/ui/main/MainActivity.java @@ -1,21 +1,17 @@ package org.autojs.autojs.ui.main; import android.Manifest; -import android.annotation.SuppressLint; import android.content.Intent; import android.content.pm.PackageManager; -import android.os.Build; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.design.widget.FloatingActionButton; import android.support.design.widget.TabLayout; -import android.support.v4.app.ActivityCompat; 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.Menu; import android.view.MenuItem; @@ -23,40 +19,12 @@ import android.view.View; import com.stardust.app.FragmentPagerAdapterBuilder; import com.stardust.app.OnActivityResultDelegate; -import com.stardust.autojs.core.image.OpenCVHelper; import com.stardust.autojs.core.permission.OnRequestPermissionsResultCallback; import com.stardust.autojs.core.permission.PermissionRequestProxyActivity; import com.stardust.autojs.core.permission.RequestPermissionCallbacks; import com.stardust.enhancedfloaty.FloatyService; import com.stardust.pio.PFiles; - -import org.autojs.autojs.BuildConfig; -import org.autojs.autojs.Pref; -import org.autojs.autojs.R; -import org.autojs.autojs.autojs.AutoJs; -import org.autojs.autojs.model.indices.AndroidClassIndices; -import org.autojs.autojs.storage.file.StorageFileProvider; -import org.autojs.autojs.timing.TimedTaskManager; -import org.autojs.autojs.tool.AccessibilityServiceTool; -import org.autojs.autojs.ui.BaseActivity; -import org.autojs.autojs.ui.common.NotAskAgainDialog; -import org.autojs.autojs.ui.doc.DocsFragment_; -import org.autojs.autojs.ui.floating.FloatyWindowManger; -import org.autojs.autojs.ui.log.LogActivity_; -import org.autojs.autojs.ui.main.community.CommunityFragment; -import org.autojs.autojs.ui.main.community.CommunityFragment_; -import org.autojs.autojs.ui.main.sample.SampleListFragment_; -import org.autojs.autojs.ui.main.scripts.MyScriptListFragment_; -import org.autojs.autojs.ui.main.task.TaskManagerFragment_; -import org.autojs.autojs.ui.settings.SettingsActivity_; -import org.autojs.autojs.ui.update.VersionGuard; -import org.autojs.autojs.ui.widget.CommonMarkdownView; -import org.autojs.autojs.ui.widget.SearchViewItem; - import com.stardust.theme.ThemeColorManager; - -import org.autojs.autojs.theme.dialog.ThemeColorMaterialDialogBuilder; - import com.stardust.util.BackPressedHandler; import com.stardust.util.DeveloperUtils; import com.stardust.util.DrawerAutoClose; @@ -65,14 +33,31 @@ import org.androidannotations.annotations.AfterViews; import org.androidannotations.annotations.Click; import org.androidannotations.annotations.EActivity; import org.androidannotations.annotations.ViewById; +import org.autojs.autojs.BuildConfig; +import org.autojs.autojs.Pref; +import org.autojs.autojs.R; +import org.autojs.autojs.autojs.AutoJs; +import org.autojs.autojs.model.explorer.Explorers; +import org.autojs.autojs.tool.AccessibilityServiceTool; +import org.autojs.autojs.ui.BaseActivity; +import org.autojs.autojs.ui.common.NotAskAgainDialog; +import org.autojs.autojs.ui.doc.DocsFragment_; +import org.autojs.autojs.ui.floating.FloatyWindowManger; +import org.autojs.autojs.ui.log.LogActivity_; +import org.autojs.autojs.ui.main.community.CommunityFragment; +import org.autojs.autojs.ui.main.community.CommunityFragment_; +import org.autojs.autojs.ui.main.sample.MarketFragment_; +import org.autojs.autojs.ui.main.scripts.MyScriptListFragment_; +import org.autojs.autojs.ui.main.task.TaskManagerFragment_; +import org.autojs.autojs.ui.settings.SettingsActivity_; +import org.autojs.autojs.ui.update.VersionGuard; +import org.autojs.autojs.ui.widget.CommonMarkdownView; +import org.autojs.autojs.ui.widget.SearchViewItem; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; -import org.opencv.core.Core; import java.util.Arrays; -import io.reactivex.android.schedulers.AndroidSchedulers; - @EActivity(R.layout.activity_main) public class MainActivity extends BaseActivity implements OnActivityResultDelegate.DelegateHost, BackPressedHandler.HostActivity, PermissionRequestProxyActivity { @@ -178,10 +163,10 @@ 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_script) + .add(new MyScriptListFragment_(), R.string.text_file) .add(new DocsFragment_(), R.string.text_tutorial) .add(new CommunityFragment_(), R.string.text_community) - .add(new SampleListFragment_(), R.string.text_sample) + .add(new MarketFragment_(), R.string.text_sample) .add(new TaskManagerFragment_(), R.string.text_manage) .build(); mViewPager.setAdapter(mPagerAdapter); @@ -250,7 +235,7 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega return; } if (getGrantResult(Manifest.permission.READ_EXTERNAL_STORAGE, permissions, grantResults) == PackageManager.PERMISSION_GRANTED) { - StorageFileProvider.getDefault().notifyStoragePermissionGranted(); + Explorers.workspace().refreshAll(); } } diff --git a/app/src/main/java/org/autojs/autojs/ui/main/community/CommunityWebView.java b/app/src/main/java/org/autojs/autojs/ui/main/community/CommunityWebView.java index 63eefadf..4ccecd7e 100644 --- a/app/src/main/java/org/autojs/autojs/ui/main/community/CommunityWebView.java +++ b/app/src/main/java/org/autojs/autojs/ui/main/community/CommunityWebView.java @@ -10,9 +10,9 @@ import android.webkit.ValueCallback; import android.webkit.WebView; import android.widget.Toast; +import org.autojs.autojs.Pref; import org.autojs.autojs.R; import org.autojs.autojs.network.NodeBB; -import org.autojs.autojs.storage.file.StorageFileProvider; import org.autojs.autojs.model.script.Scripts; import org.autojs.autojs.network.download.DownloadManager; import org.autojs.autojs.ui.common.OptionListView; @@ -24,7 +24,6 @@ import java.util.regex.Pattern; import butterknife.OnClick; import butterknife.Optional; -import io.reactivex.Observable; import io.reactivex.android.schedulers.AndroidSchedulers; /** @@ -134,7 +133,7 @@ public class CommunityWebView extends EWebView { } new FileChooserDialogBuilder(getContext()) .title(R.string.text_select_file_to_upload) - .dir(StorageFileProvider.getDefaultDirectoryPath()) + .dir(Pref.getScriptDirPath()) .singleChoice(file -> callback.onReceiveValue(Uri.fromFile(file))) .cancelListener(dialog -> callback.onReceiveValue(null)) .show(); diff --git a/app/src/main/java/org/autojs/autojs/ui/main/sample/SampleListFragment.java b/app/src/main/java/org/autojs/autojs/ui/main/sample/MarketFragment.java similarity index 67% rename from app/src/main/java/org/autojs/autojs/ui/main/sample/SampleListFragment.java rename to app/src/main/java/org/autojs/autojs/ui/main/sample/MarketFragment.java index 7a550b51..833a8e10 100644 --- a/app/src/main/java/org/autojs/autojs/ui/main/sample/SampleListFragment.java +++ b/app/src/main/java/org/autojs/autojs/ui/main/sample/MarketFragment.java @@ -6,11 +6,9 @@ import android.support.annotation.Nullable; import android.support.design.widget.FloatingActionButton; import org.autojs.autojs.R; -import org.autojs.autojs.storage.file.SampleFileProvider; -import org.autojs.autojs.model.script.Scripts; import org.autojs.autojs.ui.main.QueryEvent; import org.autojs.autojs.ui.main.ViewPagerFragment; -import org.autojs.autojs.ui.main.scripts.ScriptListView; +import org.autojs.autojs.ui.main.scripts.ExplorerView; import com.stardust.util.BackPressedHandler; import org.androidannotations.annotations.AfterViews; @@ -22,17 +20,14 @@ import org.greenrobot.eventbus.Subscribe; /** * Created by Stardust on 2017/10/28. */ -@EFragment(R.layout.fragment_sample_list) -public class SampleListFragment extends ViewPagerFragment implements BackPressedHandler { +@EFragment(R.layout.fragment_market) +public class MarketFragment extends ViewPagerFragment implements BackPressedHandler { - public SampleListFragment() { + public MarketFragment() { super(ROTATION_GONE); } - @ViewById(R.id.sample_list) - ScriptListView mScriptFileList; - @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -41,9 +36,7 @@ public class SampleListFragment extends ViewPagerFragment implements BackPressed @AfterViews void setUpViews() { - mScriptFileList.setDirectorySpanSize(2); - mScriptFileList.setStorageFileProvider(new SampleFileProvider(getContext())); - mScriptFileList.setOnScriptFileClickListener((view, file) -> Scripts.edit(file)); + } @Override @@ -70,10 +63,7 @@ public class SampleListFragment extends ViewPagerFragment implements BackPressed @Override public boolean onBackPressed(Activity activity) { - if (mScriptFileList.canGoBack()) { - mScriptFileList.goBack(); - return true; - } + return false; } @@ -84,11 +74,9 @@ public class SampleListFragment extends ViewPagerFragment implements BackPressed return; } if (event == QueryEvent.CLEAR) { - mScriptFileList.setFilter(null); return; } - String query = event.getQuery(); - mScriptFileList.setFilter((file -> file.getSimplifiedName().contains(query))); + } diff --git a/app/src/main/java/org/autojs/autojs/ui/main/sample/SampleListView.java b/app/src/main/java/org/autojs/autojs/ui/main/sample/SampleListView.java deleted file mode 100644 index 09647c56..00000000 --- a/app/src/main/java/org/autojs/autojs/ui/main/sample/SampleListView.java +++ /dev/null @@ -1,148 +0,0 @@ -package org.autojs.autojs.ui.main.sample; - -import android.content.Context; -import android.graphics.drawable.GradientDrawable; -import android.support.annotation.Nullable; -import android.support.design.widget.Snackbar; -import android.support.v4.content.res.ResourcesCompat; -import android.util.AttributeSet; -import android.view.LayoutInflater; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.widget.PopupMenu; -import android.widget.TextView; - -import com.stardust.pio.PFiles; -import org.autojs.autojs.R; -import org.autojs.autojs.storage.file.SampleFileProvider; -import org.autojs.autojs.model.script.ScriptFile; -import org.autojs.autojs.model.script.Scripts; -import org.autojs.autojs.ui.common.ScriptOperations; -import org.autojs.autojs.ui.main.scripts.ScriptListView; -import org.autojs.autojs.ui.widget.BindableViewHolder; - -import java.io.File; - -import butterknife.BindView; -import butterknife.ButterKnife; -import butterknife.OnClick; - -/** - * Created by Stardust on 2017/10/28. - */ - -public class SampleListView extends ScriptListView { - public SampleListView(Context context) { - super(context); - } - - public SampleListView(Context context, @Nullable AttributeSet attrs) { - super(context, attrs); - } - - @Override - public boolean onMenuItemClick(MenuItem item) { - switch (item.getItemId()) { - case R.id.copy_to_my_script: - new ScriptOperations(getContext(), this) - .importFile(mSelectedScriptFile.getPath()) - .subscribe(); - return true; - case R.id.reset: - resetSample(); - return true; - default: - return super.onMenuItemClick(item); - } - } - - private void resetSample() { - String samplePath = new File(getCurrentDirectory(), mSelectedScriptFile.getName()).getPath(); - if (SampleFileProvider.copySample(getContext(), samplePath, mSelectedScriptFile.getPath())) { - Snackbar.make(this, R.string.text_reset_succeed, Snackbar.LENGTH_SHORT).show(); - } else { - Snackbar.make(this, R.string.text_reset_fail, Snackbar.LENGTH_SHORT).show(); - } - } - - @Override - protected BindableViewHolder onCreateViewHolder(LayoutInflater inflater, ViewGroup parent, int viewType) { - if (viewType == VIEW_TYPE_FILE) { - return new SampleFileViewHolder(inflater.inflate(R.layout.script_file_list_file, parent, false)); - } else if (viewType == VIEW_TYPE_DIRECTORY) { - DirectoryViewHolder viewHolder = (DirectoryViewHolder) super.onCreateViewHolder(inflater, parent, viewType); - viewHolder.mOptions.setVisibility(GONE); - return viewHolder; - } - return super.onCreateViewHolder(inflater, parent, viewType); - } - - class SampleFileViewHolder extends BindableViewHolder { - - @BindView(R.id.name) - TextView mName; - @BindView(R.id.first_char) - TextView mFirstChar; - @BindView(R.id.desc) - TextView mDesc; - @BindView(R.id.more) - View mOptions; - @BindView(R.id.edit) - View mEdit; - GradientDrawable mFirstCharBackground; - private ScriptFile mScriptFile; - - SampleFileViewHolder(View itemView) { - super(itemView); - ButterKnife.bind(this, itemView); - mFirstCharBackground = (GradientDrawable) mFirstChar.getBackground(); - } - - @Override - public void bind(ScriptFile file, int position) { - mScriptFile = file; - mName.setText(file.getSimplifiedName()); - mDesc.setText(PFiles.getHumanReadableSize(file.length())); - if (file.getType() == ScriptFile.TYPE_JAVA_SCRIPT) { - mFirstChar.setText("J"); - mFirstCharBackground.setColor(ResourcesCompat.getColor(getResources(), R.color.color_j, getContext().getTheme())); - mEdit.setVisibility(VISIBLE); - } else { - mFirstChar.setText("R"); - mFirstCharBackground.setColor(ResourcesCompat.getColor(getResources(), R.color.color_r, getContext().getTheme())); - mEdit.setVisibility(GONE); - } - } - - @OnClick(R.id.item) - void onItemClick() { - if (mOnScriptFileClickListener != null) { - mOnScriptFileClickListener.onScriptFileClick(itemView, mScriptFile); - } - notifyOperated(); - } - - @OnClick(R.id.run) - void run() { - Scripts.run(mScriptFile); - notifyOperated(); - } - - @OnClick(R.id.edit) - void edit() { - Scripts.edit(mScriptFile); - notifyOperated(); - } - - @OnClick(R.id.more) - void showOptionMenu() { - mSelectedScriptFile = mScriptFile; - PopupMenu popupMenu = new PopupMenu(getContext(), mOptions); - popupMenu.inflate(R.menu.menu_sample_options); - popupMenu.setOnMenuItemClickListener(SampleListView.this); - popupMenu.show(); - } - } - -} diff --git a/app/src/main/java/org/autojs/autojs/ui/main/scripts/ScriptListView.java b/app/src/main/java/org/autojs/autojs/ui/main/scripts/ExplorerView.java similarity index 52% rename from app/src/main/java/org/autojs/autojs/ui/main/scripts/ScriptListView.java rename to app/src/main/java/org/autojs/autojs/ui/main/scripts/ExplorerView.java index 20f044e6..d79fb1de 100644 --- a/app/src/main/java/org/autojs/autojs/ui/main/scripts/ScriptListView.java +++ b/app/src/main/java/org/autojs/autojs/ui/main/scripts/ExplorerView.java @@ -4,7 +4,6 @@ import android.annotation.SuppressLint; import android.content.Context; import android.graphics.drawable.GradientDrawable; import android.support.annotation.Nullable; -import android.support.v4.content.res.ResourcesCompat; import android.support.v4.widget.SwipeRefreshLayout; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; @@ -17,22 +16,28 @@ import android.widget.ImageView; import android.widget.PopupMenu; import android.widget.TextView; -import com.stardust.pio.PFile; import com.stardust.pio.PFiles; + import org.autojs.autojs.R; +import org.autojs.autojs.model.explorer.Explorer; +import org.autojs.autojs.model.explorer.ExplorerChangeEvent; +import org.autojs.autojs.model.explorer.ExplorerItem; +import org.autojs.autojs.model.explorer.ExplorerPage; import org.autojs.autojs.model.script.ScriptFile; import org.autojs.autojs.model.script.Scripts; -import org.autojs.autojs.storage.file.StorageFileProvider; import org.autojs.autojs.ui.build.BuildActivity; import org.autojs.autojs.ui.build.BuildActivity_; import org.autojs.autojs.ui.common.ScriptLoopDialog; import org.autojs.autojs.ui.common.ScriptOperations; -import org.autojs.autojs.ui.viewmodel.ScriptList; +import org.autojs.autojs.ui.explorer.ExplorerViewHelper; +import org.autojs.autojs.ui.viewmodel.ExplorerItemList; import org.autojs.autojs.ui.widget.BindableViewHolder; import org.autojs.autojs.theme.widget.ThemeColorSwipeRefreshLayout; import org.greenrobot.eventbus.Subscribe; +import java.util.Stack; + import butterknife.BindView; import butterknife.ButterKnife; import butterknife.OnClick; @@ -45,83 +50,93 @@ import io.reactivex.schedulers.Schedulers; * Created by Stardust on 2017/8/21. */ -public class ScriptListView extends ThemeColorSwipeRefreshLayout implements SwipeRefreshLayout.OnRefreshListener, PopupMenu.OnMenuItemClickListener { +public class ExplorerView extends ThemeColorSwipeRefreshLayout implements SwipeRefreshLayout.OnRefreshListener, PopupMenu.OnMenuItemClickListener { + private static final String LOG_TAG = "ExplorerView"; - private static final String LOG_TAG = "ScriptListView"; - - public interface OnScriptFileClickListener { - void onScriptFileClick(View view, ScriptFile file); + public interface OnItemClickListener { + void onItemClick(View view, ExplorerItem item); } public interface OnItemOperatedListener { - void OnItemOperated(ScriptFile file); + void OnItemOperated(ExplorerItem item); } - protected static final int VIEW_TYPE_FILE = 0; - protected static final int VIEW_TYPE_DIRECTORY = 1; + protected static final int VIEW_TYPE_ITEM = 0; + protected static final int VIEW_TYPE_PAGE = 1; //category是类别,也即"文件", "文件夹"那两个 protected static final int VIEW_TYPE_CATEGORY = 2; private static final int positionOfCategoryDir = 0; - private ScriptList mScriptList = new ScriptList(); - private RecyclerView mScriptListView; - private ScriptListAdapter mScriptListAdapter = new ScriptListAdapter(); - private ScriptFile mCurrentDirectory; - protected OnScriptFileClickListener mOnScriptFileClickListener; - private Function mFilter; - private OnItemOperatedListener mOnItemOperatedListener; - protected ScriptFile mSelectedScriptFile; - private StorageFileProvider mStorageFileProvider; - private boolean mDirSortMenuShowing = false; - private boolean mDirsCollapsed; - private boolean mFilesCollapsed; - private int mDirectorySpanSize = 1; - public ScriptListView(Context context) { + private ExplorerItemList mExplorerItemList = new ExplorerItemList(); + private RecyclerView mExplorerItemListView; + private ExplorerAdapter mExplorerAdapter = new ExplorerAdapter(); + protected OnItemClickListener mOnItemClickListener; + private Function mFilter; + private OnItemOperatedListener mOnItemOperatedListener; + protected ExplorerItem mSelectedItem; + private Explorer mExplorer; + private Stack mPageStateHistory = new Stack<>(); + private ExplorerPageState mCurrentPageState = new ExplorerPageState(); + private boolean mDirSortMenuShowing = false; + private int mDirectorySpanSize = 2; + + public ExplorerView(Context context) { super(context); init(); } - public ScriptListView(Context context, @Nullable AttributeSet attrs) { + public ExplorerView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); init(); } - public ScriptFile getCurrentDirectory() { - return mCurrentDirectory; + public ExplorerPage getCurrentPage() { + return mCurrentPageState.page; } - public void setCurrentDirectory(ScriptFile currentDirectory) { - mCurrentDirectory = currentDirectory; - mDirsCollapsed = false; - mFilesCollapsed = false; - loadScriptList(); - } - - public void setOnScriptFileClickListener(OnScriptFileClickListener onScriptFileClickListener) { - mOnScriptFileClickListener = onScriptFileClickListener; - } - - public void setStorageFileProvider(StorageFileProvider storageFileProvider) { - setStorageFileProvider(storageFileProvider, new ScriptFile(storageFileProvider.getInitialDirectory())); + public void setRootPage(ExplorerPage page) { + mPageStateHistory.clear(); + mCurrentPageState = new ExplorerPageState(page); + loadItemList(); } - public void setSortConfig(ScriptList.SortConfig sortConfig) { - mScriptList.setSortConfig(sortConfig); + public void enterChildPage(ExplorerPage childItemGroup) { + mPageStateHistory.push(mCurrentPageState); + mCurrentPageState = new ExplorerPageState(childItemGroup); + loadItemList(); } - public ScriptList.SortConfig getSortConfig() { - return mScriptList.getSortConfig(); + public void setOnItemClickListener(OnItemClickListener onItemClickListener) { + mOnItemClickListener = onItemClickListener; } - public void setStorageFileProvider(StorageFileProvider fileProvider, ScriptFile currentDirectory) { - if (mStorageFileProvider != null) - mStorageFileProvider.unregisterDirectoryChangeListener(this); - mStorageFileProvider = fileProvider; - setCurrentDirectory(currentDirectory); - mStorageFileProvider.registerDirectoryChangeListener(this); + public void setSortConfig(ExplorerItemList.SortConfig sortConfig) { + mExplorerItemList.setSortConfig(sortConfig); + } + + public ExplorerItemList.SortConfig getSortConfig() { + return mExplorerItemList.getSortConfig(); + } + + public void setExplorer(Explorer explorer, ExplorerPage rootPage) { + if (mExplorer != null) + mExplorer.unregisterChangeListener(this); + mExplorer = explorer; + setRootPage(rootPage); + mExplorer.registerChangeListener(this); + } + + public void setExplorer(Explorer explorer, ExplorerPage rootPage, ExplorerPage currentPage) { + if (mExplorer != null) + mExplorer.unregisterChangeListener(this); + mExplorer = explorer; + mPageStateHistory.clear(); + mCurrentPageState = new ExplorerPageState(rootPage); + mExplorer.registerChangeListener(this); + enterChildPage(currentPage); } public void setOnItemOperatedListener(OnItemOperatedListener onItemOperatedListener) { @@ -129,35 +144,36 @@ public class ScriptListView extends ThemeColorSwipeRefreshLayout implements Swip } public boolean canGoBack() { - return !mCurrentDirectory.equals(mStorageFileProvider.getInitialDirectory()); + return !mPageStateHistory.empty(); } public void goBack() { - setCurrentDirectory(mCurrentDirectory.getParentFile()); + mCurrentPageState = mPageStateHistory.pop(); + loadItemList(); } public void setDirectorySpanSize(int directorySpanSize) { mDirectorySpanSize = directorySpanSize; } - public void setFilter(Function filter) { + public void setFilter(Function filter) { mFilter = filter; reload(); } public void reload() { - loadScriptList(); + loadItemList(); } private void init() { setOnRefreshListener(this); - mScriptListView = new RecyclerView(getContext()); - addView(mScriptListView); - initScriptListRecyclerView(); + mExplorerItemListView = new RecyclerView(getContext()); + addView(mExplorerItemListView); + initExplorerItemListView(); } - private void initScriptListRecyclerView() { - mScriptListView.setAdapter(mScriptListAdapter); + private void initExplorerItemListView() { + mExplorerItemListView.setAdapter(mExplorerAdapter); GridLayoutManager manager = new GridLayoutManager(getContext(), 2); manager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { @Override @@ -170,102 +186,105 @@ public class ScriptListView extends ThemeColorSwipeRefreshLayout implements Swip return 2; } }); - mScriptListView.setLayoutManager(manager); + mExplorerItemListView.setLayoutManager(manager); } private int positionOfCategoryFile() { - if (mDirsCollapsed) + if (mCurrentPageState.dirsCollapsed) return 1; - return mScriptList.directoryCount() + 1; + return mExplorerItemList.groupCount() + 1; } - private void loadScriptList() { + @SuppressLint("CheckResult") + private void loadItemList() { setRefreshing(true); - mStorageFileProvider.getDirectoryFiles(mCurrentDirectory) + mExplorer.fetchChildren(mCurrentPageState.page) .subscribeOn(Schedulers.io()) - .filter(f -> mFilter == null ? true : mFilter.apply(f)) - .collectInto(mScriptList.cloneConfig(), (list, file) -> { - if (file instanceof ScriptFile) { - list.add((ScriptFile) file); - } else { - list.add(new ScriptFile(file)); - } + .flatMapObservable(page -> { + mCurrentPageState.page = page; + return Observable.fromIterable(page); }) + .filter(f -> mFilter == null ? true : mFilter.apply(f)) + .collectInto(mExplorerItemList.cloneConfig(), ExplorerItemList::add) .observeOn(Schedulers.computation()) - .doOnSuccess(ScriptList::sort) + .doOnSuccess(ExplorerItemList::sort) .observeOn(AndroidSchedulers.mainThread()) .subscribe(list -> { - mScriptList = list; - mScriptListAdapter.notifyDataSetChanged(); + mExplorerItemList = list; + mExplorerAdapter.notifyDataSetChanged(); setRefreshing(false); }); } @Subscribe - public void onDirectoryChange(StorageFileProvider.DirectoryChangeEvent event) { - if (!event.getDir().equals(mCurrentDirectory)) { - return; + public void onExplorerChange(ExplorerChangeEvent event) { + if (event.getAction() == ExplorerChangeEvent.ALL + || mCurrentPageState.page.equals(event.getItemGroup())) { + loadItemList(); } - loadScriptList(); } @Override public void onRefresh() { - mStorageFileProvider.notifyDirectoryChanged(mCurrentDirectory); + mExplorer.notifyChildrenChanged(mCurrentPageState.page); } + public ScriptFile getCurrentDirectory() { + return getCurrentPage().toScriptFile(); + } + @Override public boolean onMenuItemClick(MenuItem item) { switch (item.getItemId()) { case R.id.rename: - new ScriptOperations(getContext(), this, getCurrentDirectory()) - .rename(mSelectedScriptFile) + new ScriptOperations(getContext(), this, getCurrentPage()) + .rename(mSelectedItem.toScriptFile()) .subscribe(); break; case R.id.delete: - new ScriptOperations(getContext(), this, getCurrentDirectory()) - .delete(mSelectedScriptFile); + new ScriptOperations(getContext(), this, getCurrentPage()) + .delete(mSelectedItem.toScriptFile()); break; case R.id.run_repeatedly: - new ScriptLoopDialog(getContext(), mSelectedScriptFile) + new ScriptLoopDialog(getContext(), mSelectedItem.toScriptFile()) .show(); notifyOperated(); break; case R.id.create_shortcut: - new ScriptOperations(getContext(), this, getCurrentDirectory()) - .createShortcut(mSelectedScriptFile); + new ScriptOperations(getContext(), this, getCurrentPage()) + .createShortcut(mSelectedItem.toScriptFile()); break; case R.id.open_by_other_apps: - Scripts.openByOtherApps(mSelectedScriptFile); + Scripts.openByOtherApps(mSelectedItem.toScriptFile()); notifyOperated(); break; case R.id.send: - Scripts.send(mSelectedScriptFile); + Scripts.send(mSelectedItem.toScriptFile()); notifyOperated(); break; case R.id.timed_task: - new ScriptOperations(getContext(), this, getCurrentDirectory()) - .timedTask(mSelectedScriptFile); + new ScriptOperations(getContext(), this, getCurrentPage()) + .timedTask(mSelectedItem.toScriptFile()); notifyOperated(); break; case R.id.action_build_apk: BuildActivity_.intent(getContext()) - .extra(BuildActivity.EXTRA_SOURCE_FILE, mSelectedScriptFile.getPath()) + .extra(BuildActivity.EXTRA_SOURCE_FILE, mSelectedItem.getPath()) .start(); notifyOperated(); break; case R.id.action_sort_by_date: - sort(ScriptList.SORT_TYPE_DATE, mDirSortMenuShowing); + sort(ExplorerItemList.SORT_TYPE_DATE, mDirSortMenuShowing); break; case R.id.action_sort_by_type: - sort(ScriptList.SORT_TYPE_TYPE, mDirSortMenuShowing); + sort(ExplorerItemList.SORT_TYPE_TYPE, mDirSortMenuShowing); break; case R.id.action_sort_by_name: - sort(ScriptList.SORT_TYPE_NAME, mDirSortMenuShowing); + sort(ExplorerItemList.SORT_TYPE_NAME, mDirSortMenuShowing); break; case R.id.action_sort_by_size: - sort(ScriptList.SORT_TYPE_SIZE, mDirSortMenuShowing); + sort(ExplorerItemList.SORT_TYPE_SIZE, mDirSortMenuShowing); break; default: return false; @@ -275,7 +294,7 @@ public class ScriptListView extends ThemeColorSwipeRefreshLayout implements Swip protected void notifyOperated() { if (mOnItemOperatedListener != null) { - mOnItemOperatedListener.OnItemOperated(mSelectedScriptFile); + mOnItemOperatedListener.OnItemOperated(mSelectedItem); } } @@ -284,17 +303,17 @@ public class ScriptListView extends ThemeColorSwipeRefreshLayout implements Swip setRefreshing(true); Observable.fromCallable(() -> { if (isDir) { - mScriptList.sortDir(sortType); + mExplorerItemList.sortItemGroup(sortType); } else { - mScriptList.sortFile(sortType); + mExplorerItemList.sortFile(sortType); } - return mScriptList; + return mExplorerItemList; }) .subscribeOn(Schedulers.computation()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(o -> { - mScriptListAdapter.notifyDataSetChanged(); + mExplorerAdapter.notifyDataSetChanged(); setRefreshing(false); }); } @@ -303,38 +322,38 @@ public class ScriptListView extends ThemeColorSwipeRefreshLayout implements Swip @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); - if (mStorageFileProvider != null) - mStorageFileProvider.registerDirectoryChangeListener(this); + if (mExplorer != null) + mExplorer.registerChangeListener(this); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); - mStorageFileProvider.unregisterDirectoryChangeListener(this); + mExplorer.unregisterChangeListener(this); } protected BindableViewHolder onCreateViewHolder(LayoutInflater inflater, ViewGroup parent, int viewType) { - 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)); + if (viewType == VIEW_TYPE_ITEM) { + return new ExplorerItemViewHolder(inflater.inflate(R.layout.script_file_list_file, parent, false)); + } else if (viewType == VIEW_TYPE_PAGE) { + return new ExplorerPageViewHolder(inflater.inflate(R.layout.script_file_list_directory, parent, false)); } else { return new CategoryViewHolder(inflater.inflate(R.layout.script_file_list_category, parent, false)); } } - protected RecyclerView getScriptListView() { - return mScriptListView; + protected RecyclerView getExplorerItemListView() { + return mExplorerItemListView; } - private class ScriptListAdapter extends RecyclerView.Adapter> { + private class ExplorerAdapter extends RecyclerView.Adapter> { @Override public BindableViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { LayoutInflater inflater = LayoutInflater.from(parent.getContext()); - return ScriptListView.this.onCreateViewHolder(inflater, parent, viewType); + return ExplorerView.this.onCreateViewHolder(inflater, parent, viewType); } @SuppressWarnings("unchecked") @@ -343,15 +362,14 @@ public class ScriptListView extends ThemeColorSwipeRefreshLayout implements Swip int positionOfCategoryFile = positionOfCategoryFile(); BindableViewHolder bindableViewHolder = (BindableViewHolder) holder; if (position == positionOfCategoryDir || position == positionOfCategoryFile) { - // FIXME: 2017/10/20 java.lang.ClassCastException: java.lang.Boolean cannot be cast to org.autojs.autojs.model.script.ScriptFile bindableViewHolder.bind(position == positionOfCategoryDir, position); return; } if (position < positionOfCategoryFile) { - bindableViewHolder.bind(mScriptList.getDir(position - 1), position); + bindableViewHolder.bind(mExplorerItemList.getItemGroup(position - 1), position); return; } - bindableViewHolder.bind(mScriptList.getFile(position - positionOfCategoryFile - 1), position); + bindableViewHolder.bind(mExplorerItemList.getItem(position - positionOfCategoryFile - 1), position); } @Override @@ -360,27 +378,26 @@ public class ScriptListView extends ThemeColorSwipeRefreshLayout implements Swip if (position == positionOfCategoryDir || position == positionOfCategoryFile) { return VIEW_TYPE_CATEGORY; } else if (position < positionOfCategoryFile) { - return VIEW_TYPE_DIRECTORY; + return VIEW_TYPE_PAGE; } else { - return VIEW_TYPE_FILE; + return VIEW_TYPE_ITEM; } } @Override public int getItemCount() { int count = 0; - if (!mDirsCollapsed) { - count += mScriptList.directoryCount(); + if (!mCurrentPageState.dirsCollapsed) { + count += mExplorerItemList.groupCount(); } - if (!mFilesCollapsed) { - count += mScriptList.fileCount(); + if (!mCurrentPageState.filesCollapsed) { + count += mExplorerItemList.itemCount(); } return count + 2; } } - protected class ScriptFileViewHolder extends BindableViewHolder { - + protected class ExplorerItemViewHolder extends BindableViewHolder { @BindView(R.id.name) TextView mName; @@ -392,92 +409,95 @@ public class ScriptListView extends ThemeColorSwipeRefreshLayout implements Swip View mOptions; @BindView(R.id.edit) View mEdit; - GradientDrawable mFirstCharBackground; - private ScriptFile mScriptFile; + @BindView(R.id.run) + View mRun; - ScriptFileViewHolder(View itemView) { + GradientDrawable mFirstCharBackground; + private ExplorerItem mExplorerItem; + + ExplorerItemViewHolder(View itemView) { super(itemView); ButterKnife.bind(this, itemView); mFirstCharBackground = (GradientDrawable) mFirstChar.getBackground(); } @Override - public void bind(ScriptFile file, int position) { - mScriptFile = file; - mName.setText(file.getSimplifiedName()); - mDesc.setText(PFiles.getHumanReadableSize(file.length())); - if (file.getType() == ScriptFile.TYPE_JAVA_SCRIPT) { - mFirstChar.setText("J"); - mFirstCharBackground.setColor(ResourcesCompat.getColor(getResources(), R.color.color_j, getContext().getTheme())); - mEdit.setVisibility(VISIBLE); - } else { - mFirstChar.setText("R"); - mFirstCharBackground.setColor(ResourcesCompat.getColor(getResources(), R.color.color_r, getContext().getTheme())); - mEdit.setVisibility(GONE); - } + public void bind(ExplorerItem item, int position) { + mExplorerItem = item; + mName.setText(ExplorerViewHelper.getDisplayName(item)); + mDesc.setText(PFiles.getHumanReadableSize(item.getSize())); + mFirstChar.setText(ExplorerViewHelper.getIconText(item)); + mFirstCharBackground.setColor(ExplorerViewHelper.getIconColor(item)); + mEdit.setVisibility(item.isEditable() ? VISIBLE : GONE); + mRun.setVisibility(item.isExecutable() ? VISIBLE : GONE); } @OnClick(R.id.item) void onItemClick() { - if (mOnScriptFileClickListener != null) { - mOnScriptFileClickListener.onScriptFileClick(itemView, mScriptFile); + if (mOnItemClickListener != null) { + mOnItemClickListener.onItemClick(itemView, mExplorerItem); } notifyOperated(); } @OnClick(R.id.run) void run() { - Scripts.run(mScriptFile); + Scripts.run(new ScriptFile(mExplorerItem.getPath())); notifyOperated(); } @OnClick(R.id.edit) void edit() { - Scripts.edit(mScriptFile); + Scripts.edit(new ScriptFile(mExplorerItem.getPath())); notifyOperated(); } @OnClick(R.id.more) void showOptionMenu() { - mSelectedScriptFile = mScriptFile; + mSelectedItem = mExplorerItem; PopupMenu popupMenu = new PopupMenu(getContext(), mOptions); popupMenu.inflate(R.menu.menu_script_options); - popupMenu.setOnMenuItemClickListener(ScriptListView.this); + popupMenu.setOnMenuItemClickListener(ExplorerView.this); popupMenu.show(); } } - protected class DirectoryViewHolder extends BindableViewHolder { + protected class ExplorerPageViewHolder extends BindableViewHolder { @BindView(R.id.name) public TextView mName; + @BindView(R.id.more) public View mOptions; - private ScriptFile mScriptFile; + @BindView(R.id.icon) + public ImageView mIcon; - DirectoryViewHolder(View itemView) { + private ExplorerPage mExplorerPage; + + ExplorerPageViewHolder(View itemView) { super(itemView); ButterKnife.bind(this, itemView); } @Override - public void bind(ScriptFile data, int position) { - mName.setText(data.getSimplifiedName()); - mScriptFile = data; + public void bind(ExplorerPage data, int position) { + mName.setText(ExplorerViewHelper.getDisplayName(data)); + mIcon.setImageResource(ExplorerViewHelper.getIcon(data)); + mExplorerPage = data; } @OnClick(R.id.item) void onItemClick() { - setCurrentDirectory(mScriptFile); + enterChildPage(mExplorerPage); } @OnClick(R.id.more) void showOptionMenu() { - mSelectedScriptFile = mScriptFile; + mSelectedItem = mExplorerPage; PopupMenu popupMenu = new PopupMenu(getContext(), mOptions); popupMenu.inflate(R.menu.menu_dir_options); - popupMenu.setOnMenuItemClickListener(ScriptListView.this); + popupMenu.setOnMenuItemClickListener(ExplorerView.this); popupMenu.show(); } } @@ -516,12 +536,12 @@ public class ScriptListView extends ThemeColorSwipeRefreshLayout implements Swip mGoBack.setVisibility(GONE); } if (isDirCategory) { - mArrow.setRotation(mDirsCollapsed ? -90 : 0); - mSortOrder.setImageResource(mScriptList.isDirSortedAscending() ? + mArrow.setRotation(mCurrentPageState.dirsCollapsed ? -90 : 0); + mSortOrder.setImageResource(mExplorerItemList.isDirSortedAscending() ? R.drawable.ic_ascending_order : R.drawable.ic_descending_order); } else { - mArrow.setRotation(mFilesCollapsed ? -90 : 0); - mSortOrder.setImageResource(mScriptList.isFileSortedAscending() ? + mArrow.setRotation(mCurrentPageState.filesCollapsed ? -90 : 0); + mSortOrder.setImageResource(mExplorerItemList.isFileSortedAscending() ? R.drawable.ic_ascending_order : R.drawable.ic_descending_order); } } @@ -529,15 +549,15 @@ public class ScriptListView extends ThemeColorSwipeRefreshLayout implements Swip @OnClick(R.id.order) void changeSortOrder() { if (mIsDir) { - mSortOrder.setImageResource(mScriptList.isDirSortedAscending() ? + mSortOrder.setImageResource(mExplorerItemList.isDirSortedAscending() ? R.drawable.ic_ascending_order : R.drawable.ic_descending_order); - mScriptList.setDirSortedAscending(!mScriptList.isDirSortedAscending()); - sort(mScriptList.getDirSortType(), mIsDir); + mExplorerItemList.setDirSortedAscending(!mExplorerItemList.isDirSortedAscending()); + sort(mExplorerItemList.getDirSortType(), mIsDir); } else { - mSortOrder.setImageResource(mScriptList.isFileSortedAscending() ? + mSortOrder.setImageResource(mExplorerItemList.isFileSortedAscending() ? R.drawable.ic_ascending_order : R.drawable.ic_descending_order); - mScriptList.setFileSortedAscending(!mScriptList.isFileSortedAscending()); - sort(mScriptList.getFileSortType(), mIsDir); + mExplorerItemList.setFileSortedAscending(!mExplorerItemList.isFileSortedAscending()); + sort(mExplorerItemList.getFileSortType(), mIsDir); } } @@ -545,7 +565,7 @@ public class ScriptListView extends ThemeColorSwipeRefreshLayout implements Swip void showSortOptions() { PopupMenu popupMenu = new PopupMenu(getContext(), mSort); popupMenu.inflate(R.menu.menu_sort_options); - popupMenu.setOnMenuItemClickListener(ScriptListView.this); + popupMenu.setOnMenuItemClickListener(ExplorerView.this); mDirSortMenuShowing = mIsDir; popupMenu.show(); @@ -561,11 +581,27 @@ public class ScriptListView extends ThemeColorSwipeRefreshLayout implements Swip @OnClick(R.id.title_container) void collapseOrExpand() { if (mIsDir) { - mDirsCollapsed = !mDirsCollapsed; + mCurrentPageState.dirsCollapsed = !mCurrentPageState.dirsCollapsed; } else { - mFilesCollapsed = !mFilesCollapsed; + mCurrentPageState.filesCollapsed = !mCurrentPageState.filesCollapsed; } - mScriptListAdapter.notifyDataSetChanged(); + mExplorerAdapter.notifyDataSetChanged(); + } + } + + private static class ExplorerPageState { + + ExplorerPage page; + + boolean dirsCollapsed; + + boolean filesCollapsed; + + ExplorerPageState() { + } + + ExplorerPageState(ExplorerPage page) { + this.page = page; } } } diff --git a/app/src/main/java/org/autojs/autojs/ui/main/scripts/MyScriptListFragment.java b/app/src/main/java/org/autojs/autojs/ui/main/scripts/MyScriptListFragment.java index 4b2e69da..1151fc59 100644 --- a/app/src/main/java/org/autojs/autojs/ui/main/scripts/MyScriptListFragment.java +++ b/app/src/main/java/org/autojs/autojs/ui/main/scripts/MyScriptListFragment.java @@ -6,22 +6,22 @@ import android.preference.PreferenceManager; import android.support.annotation.Nullable; import android.support.design.widget.FloatingActionButton; -import com.stardust.autojs.script.AutoFileSource; -import org.autojs.autojs.R; -import org.autojs.autojs.model.script.ScriptFile; -import org.autojs.autojs.model.script.Scripts; -import org.autojs.autojs.storage.file.StorageFileProvider; -import org.autojs.autojs.tool.SimpleObserver; -import org.autojs.autojs.ui.common.ScriptOperations; -import org.autojs.autojs.ui.main.FloatingActionMenu; -import org.autojs.autojs.ui.main.QueryEvent; -import org.autojs.autojs.ui.main.ViewPagerFragment; -import org.autojs.autojs.ui.viewmodel.ScriptList; import com.stardust.util.BackPressedHandler; import org.androidannotations.annotations.AfterViews; import org.androidannotations.annotations.EFragment; import org.androidannotations.annotations.ViewById; +import org.autojs.autojs.Pref; +import org.autojs.autojs.R; +import org.autojs.autojs.model.explorer.ExplorerDirPage; +import org.autojs.autojs.model.explorer.Explorers; +import org.autojs.autojs.model.script.Scripts; +import org.autojs.autojs.tool.SimpleObserver; +import org.autojs.autojs.ui.common.ScriptOperations; +import org.autojs.autojs.ui.main.FloatingActionMenu; +import org.autojs.autojs.ui.main.QueryEvent; +import org.autojs.autojs.ui.main.ViewPagerFragment; +import org.autojs.autojs.ui.viewmodel.ExplorerItemList; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; @@ -40,7 +40,7 @@ public class MyScriptListFragment extends ViewPagerFragment implements BackPress } @ViewById(R.id.script_file_list) - ScriptListView mScriptFileList; + ExplorerView mExplorerView; private FloatingActionMenu mFloatingActionMenu; @@ -52,12 +52,12 @@ public class MyScriptListFragment extends ViewPagerFragment implements BackPress @AfterViews void setUpViews() { - ScriptList.SortConfig sortConfig = ScriptList.SortConfig.from(PreferenceManager.getDefaultSharedPreferences(getContext())); - mScriptFileList.setSortConfig(sortConfig); - mScriptFileList.setStorageFileProvider(StorageFileProvider.getDefault()); - mScriptFileList.setOnScriptFileClickListener((view, file) -> { - if (file.getType() == ScriptFile.TYPE_JAVA_SCRIPT) { - Scripts.edit(file); + ExplorerItemList.SortConfig sortConfig = ExplorerItemList.SortConfig.from(PreferenceManager.getDefaultSharedPreferences(getContext())); + mExplorerView.setSortConfig(sortConfig); + mExplorerView.setExplorer(Explorers.workspace(), ExplorerDirPage.createRoot(Pref.getScriptDirPath())); + mExplorerView.setOnItemClickListener((view, item) -> { + if (item.isEditable()) { + Scripts.edit(item.toScriptFile()); } }); } @@ -113,8 +113,8 @@ public class MyScriptListFragment extends ViewPagerFragment implements BackPress mFloatingActionMenu.collapse(); return true; } - if (mScriptFileList.canGoBack()) { - mScriptFileList.goBack(); + if (mExplorerView.canGoBack()) { + mExplorerView.goBack(); return true; } return false; @@ -134,17 +134,17 @@ public class MyScriptListFragment extends ViewPagerFragment implements BackPress return; } if (event == QueryEvent.CLEAR) { - mScriptFileList.setFilter(null); + mExplorerView.setFilter(null); return; } String query = event.getQuery(); - mScriptFileList.setFilter((file -> file.getSimplifiedName().contains(query))); + mExplorerView.setFilter((item -> item.getName().contains(query))); } @Override public void onStop() { super.onStop(); - mScriptFileList.getSortConfig().saveInto(PreferenceManager.getDefaultSharedPreferences(getContext())); + mExplorerView.getSortConfig().saveInto(PreferenceManager.getDefaultSharedPreferences(getContext())); } @Override @@ -163,19 +163,19 @@ public class MyScriptListFragment extends ViewPagerFragment implements BackPress @Override public void onClick(FloatingActionButton button, int pos) { - if (mScriptFileList == null) + if (mExplorerView == null) return; switch (pos) { case 0: - new ScriptOperations(getContext(), mScriptFileList, mScriptFileList.getCurrentDirectory()) + new ScriptOperations(getContext(), mExplorerView, mExplorerView.getCurrentPage()) .newDirectory(); break; case 1: - new ScriptOperations(getContext(), mScriptFileList, mScriptFileList.getCurrentDirectory()) + new ScriptOperations(getContext(), mExplorerView, mExplorerView.getCurrentPage()) .newScriptFile(); break; case 2: - new ScriptOperations(getContext(), mScriptFileList, mScriptFileList.getCurrentDirectory()) + new ScriptOperations(getContext(), mExplorerView, mExplorerView.getCurrentPage()) .importFile(); break; diff --git a/app/src/main/java/org/autojs/autojs/ui/settings/ScriptDirPathPreference.java b/app/src/main/java/org/autojs/autojs/ui/settings/ScriptDirPathPreference.java index 34479769..f308dc4a 100644 --- a/app/src/main/java/org/autojs/autojs/ui/settings/ScriptDirPathPreference.java +++ b/app/src/main/java/org/autojs/autojs/ui/settings/ScriptDirPathPreference.java @@ -13,9 +13,10 @@ import android.widget.Toast; import com.afollestad.materialdialogs.MaterialDialog; import com.afollestad.materialdialogs.prefs.MaterialEditTextPreference; +import org.autojs.autojs.Pref; import org.autojs.autojs.R; +import org.autojs.autojs.model.explorer.Explorers; import org.autojs.autojs.storage.file.FileObservable; -import org.autojs.autojs.storage.file.StorageFileProvider; import org.autojs.autojs.theme.dialog.ThemeColorMaterialDialogBuilder; import org.autojs.autojs.tool.SimpleObserver; @@ -55,18 +56,18 @@ public class ScriptDirPathPreference extends MaterialEditTextPreference { @Override protected void onDialogClosed(boolean positiveResult) { - String oldPath = StorageFileProvider.getDefaultDirectoryPath(); + String oldPath = Pref.getScriptDirPath(); super.onDialogClosed(positiveResult); if (!positiveResult) { return; } - String newPath = StorageFileProvider.getDefaultDirectoryPath(); + String newPath = Pref.getScriptDirPath(); if (TextUtils.equals(oldPath, newPath)) { return; } int id = mRadioGroup.getCheckedRadioButtonId(); if (id == R.id.none) { - StorageFileProvider.getDefault().refreshAll(); + Explorers.workspace().refreshAll(); return; } Observable fileObservable; @@ -99,7 +100,7 @@ public class ScriptDirPathPreference extends MaterialEditTextPreference { public void onError(Throwable e) { e.printStackTrace(); dialog.dismiss(); - StorageFileProvider.getDefault().refreshAll(); + Explorers.workspace().refreshAll(); Toast.makeText(getContext(), getContext().getString(R.string.text_error_copy_file, e.getMessage()), Toast.LENGTH_LONG).show(); } @@ -107,7 +108,7 @@ public class ScriptDirPathPreference extends MaterialEditTextPreference { @Override public void onComplete() { dialog.dismiss(); - StorageFileProvider.getDefault().refreshAll(); + Explorers.workspace().refreshAll(); } }); } diff --git a/app/src/main/java/org/autojs/autojs/ui/update/UpdateInfoDialogBuilder.java b/app/src/main/java/org/autojs/autojs/ui/update/UpdateInfoDialogBuilder.java index 7ad360b6..95b7e819 100644 --- a/app/src/main/java/org/autojs/autojs/ui/update/UpdateInfoDialogBuilder.java +++ b/app/src/main/java/org/autojs/autojs/ui/update/UpdateInfoDialogBuilder.java @@ -18,13 +18,15 @@ import com.afollestad.materialdialogs.MaterialDialog; import com.stardust.util.IntentUtil; import org.autojs.autojs.BuildConfig; +import org.autojs.autojs.Pref; import org.autojs.autojs.R; import org.autojs.autojs.network.download.DownloadManager; import org.autojs.autojs.network.entity.VersionInfo; -import org.autojs.autojs.storage.file.StorageFileProvider; import org.autojs.autojs.tool.IntentTool; import org.autojs.autojs.ui.widget.CommonMarkdownView; +import java.io.File; + import io.reactivex.android.schedulers.AndroidSchedulers; /** @@ -113,7 +115,7 @@ public class UpdateInfoDialogBuilder extends MaterialDialog.Builder { @SuppressLint("CheckResult") private void directlyDownload(String downloadUrl) { - final String path = StorageFileProvider.getDefaultDirectoryPath() + "AutoJs.apk"; + final String path = new File(Pref.getScriptDirPath(), "AutoJs.apk").getPath(); DownloadManager.getInstance().downloadWithProgress(getContext(), downloadUrl, path) .subscribeOn(AndroidSchedulers.mainThread()) .subscribe(file -> IntentUtil.installApk(getContext(), file.getPath()), diff --git a/app/src/main/java/org/autojs/autojs/ui/viewmodel/ScriptList.java b/app/src/main/java/org/autojs/autojs/ui/viewmodel/ExplorerItemList.java similarity index 71% rename from app/src/main/java/org/autojs/autojs/ui/viewmodel/ScriptList.java rename to app/src/main/java/org/autojs/autojs/ui/viewmodel/ExplorerItemList.java index da686214..5e9d4afc 100644 --- a/app/src/main/java/org/autojs/autojs/ui/viewmodel/ScriptList.java +++ b/app/src/main/java/org/autojs/autojs/ui/viewmodel/ExplorerItemList.java @@ -2,11 +2,10 @@ package org.autojs.autojs.ui.viewmodel; import android.content.SharedPreferences; -import org.autojs.autojs.model.script.ScriptFile; -import org.autojs.autojs.ui.main.scripts.ScriptListView; -import com.stardust.util.FileSorter; +import org.autojs.autojs.model.explorer.ExplorerItem; +import org.autojs.autojs.model.explorer.ExplorerPage; +import org.autojs.autojs.model.explorer.ExplorerSorter; -import java.io.File; import java.util.ArrayList; import java.util.Comparator; @@ -14,7 +13,7 @@ import java.util.Comparator; * Created by Stardust on 2017/9/30. */ -public class ScriptList { +public class ExplorerItemList { public static class SortConfig { @@ -83,8 +82,8 @@ public class ScriptList { public static final int SORT_TYPE_DATE = 0x40; private SortConfig mSortConfig = new SortConfig(); - private ArrayList mScriptFiles = new ArrayList<>(); - private ArrayList mDirectories = new ArrayList<>(); + private ArrayList mItems = new ArrayList<>(); + private ArrayList mItemGroups = new ArrayList<>(); public boolean isDirSortedAscending() { @@ -111,66 +110,66 @@ public class ScriptList { mSortConfig.mFileSortedAscending = fileSortedAscending; } - private Comparator getComparator(int sortType) { + private Comparator getComparator(int sortType) { switch (sortType) { case SORT_TYPE_NAME: - return FileSorter.NAME; + return ExplorerSorter.NAME; case SORT_TYPE_DATE: - return FileSorter.DATE; + return ExplorerSorter.DATE; case SORT_TYPE_SIZE: - return FileSorter.SIZE; + return ExplorerSorter.SIZE; case SORT_TYPE_TYPE: - return FileSorter.TYPE; + return ExplorerSorter.TYPE; } throw new IllegalArgumentException("unknown type " + sortType); } - public int directoryCount() { - return mDirectories.size(); + public int groupCount() { + return mItemGroups.size(); } - public int fileCount() { - return mScriptFiles.size(); + public int itemCount() { + return mItems.size(); } public void clear() { - mScriptFiles.clear(); - mDirectories.clear(); + mItems.clear(); + mItemGroups.clear(); } - public void add(ScriptFile file) { - if (file.isDirectory()) { - mDirectories.add(file); + public void add(ExplorerItem item) { + if (item instanceof ExplorerPage) { + mItemGroups.add((ExplorerPage) item); } else { - mScriptFiles.add(file); + mItems.add(item); } } - public ScriptFile getDir(int i) { - return mDirectories.get(i); + public ExplorerPage getItemGroup(int i) { + return mItemGroups.get(i); } - public ScriptFile getFile(int i) { - return mScriptFiles.get(i); + public ExplorerItem getItem(int i) { + return mItems.get(i); } public int count() { - return mScriptFiles.size() + mDirectories.size(); + return mItems.size() + mItemGroups.size(); } - public void sortDir(int sortType) { + public void sortItemGroup(int sortType) { mSortConfig.mDirSortType = sortType; - FileSorter.sort(mDirectories, getComparator(sortType), mSortConfig.mDirSortedAscending); + ExplorerSorter.sort(mItemGroups, getComparator(sortType), mSortConfig.mDirSortedAscending); } public void sortFile(int sortType) { mSortConfig.mFileSortType = sortType; - FileSorter.sort(mScriptFiles, getComparator(sortType), mSortConfig.mFileSortedAscending); + ExplorerSorter.sort(mItems, getComparator(sortType), mSortConfig.mFileSortedAscending); } public void sort() { - FileSorter.sort(mDirectories, getComparator(mSortConfig.mDirSortType), mSortConfig.mDirSortedAscending); - FileSorter.sort(mScriptFiles, getComparator(mSortConfig.mFileSortType), mSortConfig.mFileSortedAscending); + ExplorerSorter.sort(mItemGroups, getComparator(mSortConfig.mDirSortType), mSortConfig.mDirSortedAscending); + ExplorerSorter.sort(mItems, getComparator(mSortConfig.mFileSortType), mSortConfig.mFileSortedAscending); } public SortConfig getSortConfig() { @@ -181,8 +180,8 @@ public class ScriptList { mSortConfig = sortConfig; } - public ScriptList cloneConfig() { - ScriptList list = new ScriptList(); + public ExplorerItemList cloneConfig() { + ExplorerItemList list = new ExplorerItemList(); list.mSortConfig = mSortConfig; return list; } diff --git a/app/src/main/res/drawable-xhdpi/ic_sample_dir.png b/app/src/main/res/drawable-xhdpi/ic_sample_dir.png new file mode 100644 index 0000000000000000000000000000000000000000..769899a0a37a73f720354559b220c8204177eb22 GIT binary patch literal 2496 zcmZXWc{J4D8^`Zw1~Zs3_6cDoOTLjMdxfD95(!08Mp`7{YiJluL!zCCD9e;ewjs&a zHcauAvX*RPNhM*%HZ^3+Z+`#%&iUPQ?!C{w_x(KQIj?iibDryNt`2AkWeETP+R2gV zF5Kz=ok%g^+HCFL4uE*F6VcW)>f~(h#cRG^O7wg(<=k1Dvo@8Zn)UC@2F-RHP$_cK zeC_BNT+O`PlBmO}sVC_XMQn*ZB!RK?#Hy4q@ zWC%bS$j-$lJ~U7w0LL1HY)Ip20O7uz(7oYYz;5rlrE?nS^?L<2OUURA&QoGDZ2)d`2#_*#bUq!CNAV!!B~QnH{)`E@OnHDOg0VG2o`vkQ=v~zh5w5C< zs)RcReqSp}5Bz%Ag8X1)0Ap`_Ec=){qLD~l zAl(KP@(~dPFYM`$rewRF+w~jz2y;KmOg->|yG9@LJsHY5ky%YpK!BkUWY7BLq;NwB zJk|7@v#r1V^GU$lir@G^VU%I-B@1}d=WC*BB|rp4yJXUSV>`NJ>6yEwbnCyB{&PFCdOrK@Ofq#oKQhRKdsb3w)vlrF)w2ss2f|Z3G;!#4 zq2E>WCZ!!Btx$z8=HS8oRr0aR%lMefzh3+0Eso&ZHgv02Zo?U#m?w`0)1<+lYV}`M zZs;$kaT-vM^z+H);>(Y}nnw2xqk|hUbJ3_$<*iC8HlpQH@qNfy6;^K6Vz#abFpzqA z9AB?mdhJfi^tP~7y<308c~7?)_KKBVU@x)tM8%Z&RU656YnR}Mzv zinb>6zsPLIVk-&v|SYLX(yUqXtp}!fwf-apAE-8JzOKl!~(4 z6>DCdW z)Olim=$UC2-Pz{K3U`j*E_Zbea!_VkO~1Ny1KqYjDW`OM`{(8O!iGR_G~NC8(JR z)&qC@0O#sTGzo3uNik?V6>-m6I$VlhG7=HQg6~qjBaH;i`L;ARPiI1#b>OXotGZUN zUuCHfVELnuCA9R-_=GMoG1Iub9{)HYO}X}u#h<@#=J)>W{U@_hO2}{A+|c~2KeZ*a zoYVeKgl+G8KOZ@ekk~p%B{hH5I%sYR;gH~2Kl}{SUw97~Yg>+EObkx4t3HX)8DNSQ z>4rgq5{R&zt8_J5ZUCXkjqd}bvRn<;g~as>C*-^K7+4$$Cm--rESr~D8s2t7Ji@(e zfyxNOt4`JZ9)=e}ZMh9{le)g#qpy=E;iM=lw=J_jMd>uIF&z7%zq1TA9Sg5be;9k_ z$|_)w3msX>BZrq=Gg8=)u@o%2$)yh3oy%HpF`Ct+z)A!|D zOK&XP{3H**>GdPjWB>~|x2Z)nVar^uS`WQ9uof?aMo+4HrhIgi}MYf65L})B2u_pxa1pMuqbQ!Rv!CLxn zi;Y9)P=I6N(T(|yagMOM1!FU)xH=>=T)P0IQb`#f^m|7wz!SCS`Xc*bH~~R`GgJgc zh+=sB3*cyl1NZildT6$h+m3!ee5(tzH)d@ZOlTMLvJ+8WSfM~Vr@sye3&7M*_^Kj5 z?DEzfHH873-k^EcwA_1-h(A_i_${6=(CFuc==5+8t9<<2_xk?B^acHuPOlvKxA}ImlAbjm+|# z+2?(fXoH?%(ERo7X?6Tu{gBLo?_}MSi@AmDflutjLQbbKh@3Vsk`VSO!k-T#ys=6R z`>6#N_A|?bH=XxUIG{NK7dQ9YB`mIC7|oH`cmF5aRM(u}-Ql<^6%K^M$=;R7v?C?_ E2i}i>C;$Ke literal 0 HcmV?d00001 diff --git a/app/src/main/res/layout/activity_script_widget_settings.xml b/app/src/main/res/layout/activity_script_widget_settings.xml index c29b9490..adc55ee5 100644 --- a/app/src/main/res/layout/activity_script_widget_settings.xml +++ b/app/src/main/res/layout/activity_script_widget_settings.xml @@ -24,7 +24,7 @@ - - - \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_my_script_list.xml b/app/src/main/res/layout/fragment_my_script_list.xml index 6e3a121b..8e7a418c 100644 --- a/app/src/main/res/layout/fragment_my_script_list.xml +++ b/app/src/main/res/layout/fragment_my_script_list.xml @@ -4,7 +4,7 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - diff --git a/app/src/main/res/layout/script_file_list_directory.xml b/app/src/main/res/layout/script_file_list_directory.xml index b5c1df02..fa796a53 100644 --- a/app/src/main/res/layout/script_file_list_directory.xml +++ b/app/src/main/res/layout/script_file_list_directory.xml @@ -21,13 +21,12 @@ android:paddingTop="16dp"> + android:layout_marginRight="16dp"/> 注册中 注册失败 注册成功 - 示例 + 示例代码 导入到我的脚本 重置为初始内容 重置失败 diff --git a/autojs/src/main/assets/modules/__RootAutomator__.js b/autojs/src/main/assets/modules/__RootAutomator__.js index 3d7073e5..e80e4a28 100644 --- a/autojs/src/main/assets/modules/__RootAutomator__.js +++ b/autojs/src/main/assets/modules/__RootAutomator__.js @@ -1,6 +1,7 @@ module.exports = function(__runtime__, scope){ - function RootAutomator(nonBlockingForReady){ - this.__ra__ = Object.create(new com.stardust.autojs.core.inputevent.RootAutomator(scope.context, !nonBlockingForReady)); + function RootAutomator(inputDevice, nonBlockingForReady){ + inputDevice = inputDevice == undefined ? null : inputDevice; + this.__ra__ = Object.create(new com.stardust.autojs.core.inputevent.RootAutomator(scope.context, inputDevice, !nonBlockingForReady)); var methods = ["sendEvent", "touch", "setScreenMetrics", "touchX", "touchY", "sendSync", "sendMtSync", "tap", "swipe", "press", "longPress", "touchDown", "touchUp", "touchMove", "getDefaultId", "setDefaultId", "exit"]; for(var i = 0; i < methods.length; i++){ diff --git a/autojs/src/main/java/com/stardust/autojs/core/inputevent/InputEventCodes.java b/autojs/src/main/java/com/stardust/autojs/core/inputevent/InputEventCodes.java index 567682cc..22daf439 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/inputevent/InputEventCodes.java +++ b/autojs/src/main/java/com/stardust/autojs/core/inputevent/InputEventCodes.java @@ -9,6 +9,10 @@ package com.stardust.autojs.core.inputevent; public class InputEventCodes { + + public static final int UP = 0x00; + public static final int DOWN = 0x01; + /* * Device properties and quirks diff --git a/autojs/src/main/java/com/stardust/autojs/core/inputevent/RootAutomator.java b/autojs/src/main/java/com/stardust/autojs/core/inputevent/RootAutomator.java index b11a1ed0..3bd30802 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/inputevent/RootAutomator.java +++ b/autojs/src/main/java/com/stardust/autojs/core/inputevent/RootAutomator.java @@ -41,9 +41,15 @@ public class RootAutomator implements Shell.Callback { private final Object mReadyLock = new Object(); private volatile boolean mReady = false; private final Context mContext; + private String mInputDevice; - public RootAutomator(Context context, boolean waitForReady) throws IOException { + public RootAutomator(Context context, String inputDevice, boolean waitForReady) throws IOException { mContext = context; + if (inputDevice == null) { + mInputDevice = RootAutomatorEngine.getDeviceNameOrPath(mContext, InputDevices.getTouchDeviceName()); + } else { + mInputDevice = inputDevice; + } mShell = new Shell(true); mShell.setCallback(this); if (waitForReady) { @@ -180,19 +186,21 @@ public class RootAutomator implements Shell.Callback { sendEvent(EV_ABS, ABS_MT_POSITION_X, scaleX(x)); sendEvent(EV_ABS, ABS_MT_POSITION_Y, scaleY(y)); sendEvent(EV_ABS, ABS_MT_TOUCH_MAJOR, 5); - sendEvent(EV_SYN, SYN_REPORT, 0x00000000); + sendEvent(EV_ABS, ABS_MT_WIDTH_MAJOR, 5); + sendEvent(EV_SYN, SYN_REPORT, 0); } private void touchDown0(int x, int y, int id) throws IOException { mSlotIdMap.put(id, 0); sendEvent(EV_ABS, ABS_MT_TRACKING_ID, mTracingId.getAndIncrement()); - sendEvent(EV_KEY, BTN_TOUCH, 0x00000001); - sendEvent(EV_KEY, BTN_TOOL_FINGER, 0x00000001); + sendEvent(EV_KEY, BTN_TOUCH, DOWN); + //sendEvent(EV_KEY, BTN_TOOL_FINGER, 0x00000001); sendEvent(EV_ABS, ABS_MT_POSITION_X, scaleX(x)); sendEvent(EV_ABS, ABS_MT_POSITION_Y, scaleY(y)); //sendEvent(EV_ABS, ABS_MT_PRESSURE, 200); sendEvent(EV_ABS, ABS_MT_TOUCH_MAJOR, 5); - sendEvent(EV_SYN, SYN_REPORT, 0x00000000); + sendEvent(EV_ABS, ABS_MT_WIDTH_MAJOR, 5); + sendEvent(EV_SYN, SYN_REPORT, 0); } public void touchDown(int x, int y) throws IOException { @@ -211,8 +219,8 @@ public class RootAutomator implements Shell.Callback { sendEvent(EV_ABS, ABS_MT_SLOT, slotId); sendEvent(EV_ABS, ABS_MT_TRACKING_ID, 0xffffffff); if (mSlotIdMap.size() == 0) { - sendEvent(EV_KEY, BTN_TOUCH, 0x00000000); - sendEvent(EV_KEY, BTN_TOOL_FINGER, 0x00000000); + sendEvent(EV_KEY, BTN_TOUCH, UP); + //sendEvent(EV_KEY, BTN_TOOL_FINGER, 0x00000000); } sendEvent(EV_SYN, SYN_REPORT, 0x00000000); } diff --git a/autojs/src/main/java/com/stardust/autojs/engine/RootAutomatorEngine.java b/autojs/src/main/java/com/stardust/autojs/engine/RootAutomatorEngine.java index 395daa73..b4d5f02d 100644 --- a/autojs/src/main/java/com/stardust/autojs/engine/RootAutomatorEngine.java +++ b/autojs/src/main/java/com/stardust/autojs/engine/RootAutomatorEngine.java @@ -35,7 +35,7 @@ public class RootAutomatorEngine extends ScriptEngine.AbstractScriptEngine