refactor(ui): refactor ScriptListView

This commit is contained in:
hyb1996
2018-09-17 09:24:22 +08:00
parent c5c9aaa8e1
commit 37796048f4
48 changed files with 1219 additions and 891 deletions

View File

@@ -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();
}
}

View File

@@ -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;

View File

@@ -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 {

View File

@@ -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;
}

View File

@@ -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<String, ExplorerPage> 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<ExplorerPage> 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);
}
}

View File

@@ -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;
}
}

View File

@@ -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<ExplorerItem> 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<ExplorerItem> iterator() {
return mChildren.iterator();
}
@RequiresApi(api = Build.VERSION_CODES.N)
@Override
public void forEach(Consumer<? super ExplorerItem> action) {
mChildren.forEach(action);
}
@RequiresApi(api = Build.VERSION_CODES.N)
@Override
public Spliterator<ExplorerItem> 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);
}
}

View File

@@ -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");
}
}

View File

@@ -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<? extends ExplorerPage> 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<PFile> 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);
});
}
}

View File

@@ -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();
}

View File

@@ -0,0 +1,17 @@
package org.autojs.autojs.model.explorer;
import java.util.ArrayList;
import java.util.Collections;
public interface ExplorerPage extends ExplorerItem, Iterable<ExplorerItem> {
void copyChildren(ExplorerPage page);
boolean updateChild(ExplorerItem oldItem, ExplorerItem newItem);
boolean removeChild(ExplorerItem item);
void addChild(ExplorerItem item);
}

View File

@@ -0,0 +1,8 @@
package org.autojs.autojs.model.explorer;
import io.reactivex.Single;
public interface ExplorerProvider {
Single<? extends ExplorerPage> getExplorerPage(ExplorerPage parent);
}

View File

@@ -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;
}
}

View File

@@ -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<ExplorerItem> NAME = (o1, o2) -> collator.compare(o2.getName(), o1.getName());
public static final Comparator<ExplorerItem> DATE = (o1, o2) -> Long.compare(o1.lastModified(), o2.lastModified());
public static final Comparator<ExplorerItem> TYPE = (o1, o2) -> o2.getType().compareTo(o1.getType());
public static final Comparator<ExplorerItem> SIZE = (o1, o2) -> Long.compare(o2.getSize(), o1.getSize());
public static void sort(ExplorerItem[] items, final Comparator<ExplorerItem> 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<ExplorerItem> comparator) {
sort(items, comparator, true);
}
public static void sort(List<? extends ExplorerItem> items, final Comparator<ExplorerItem> comparator, boolean ascending) {
if (ascending) {
Collections.sort(items, comparator);
} else {
Collections.sort(items, (Comparator<ExplorerItem>) (o1, o2) -> comparator.compare(o2, o1));
}
}
public static void sort(List<? extends ExplorerItem> items, Comparator<ExplorerItem> comparator) {
sort(items, comparator, true);
}
}

View File

@@ -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;
}
}

View File

@@ -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<? extends ExplorerPage> 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<PFile> listFiles(PFile directory) {
if (directory.getPath().startsWith(mSampleDir.getPath())) {
return listSamples(directory);
}
return super.listFiles(directory);
}
private Observable<PFile> 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;
}
}

View File

@@ -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) {

View File

@@ -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);
}
}

View File

@@ -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<PFile> 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;
}
}
}

View File

@@ -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<String, List<PFile>> 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<PFile> 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<PFile> 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<PFile> 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<String, PFile> files = (Map<String, PFile>) mPFileCache.clone();
mPFileCache.clear();
mDirectoryEventBus.post(new DirectoryChangeEvent(getInitialDirectory()));
for (Map.Entry<String, PFile> 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<PFile> getInitialDirectoryFiles() {
return getDirectoryFiles(getInitialDirectory());
}
public Observable<PFile> getDirectoryFiles(PFile directory) {
List<PFile> PFiles = getFilesFromCache(directory);
if (PFiles == null) {
return listFiles(directory);
}
return Observable.fromIterable(PFiles);
}
private void clearCache(PFile directory) {
mPFileCache.remove(directory.getPath());
}
protected Observable<PFile> 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<PFile> 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);
}
}

View File

@@ -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<IntentTask> 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()

View File

@@ -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)

View File

@@ -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<String> 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<ScriptFile> download(String url) {
String fileName = DownloadManager.parseFileNameLocally(url);

View File

@@ -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;
}
}

View File

@@ -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<PFile, Integer> 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<PFile, Integer> 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<ScriptFile> {
class ExplorerItemViewHolder extends BindableViewHolder<ExplorerItem> {
@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<ScriptFile> {
class ExplorerPageViewHolder extends BindableViewHolder<ExplorerPage> {
@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());
}
}

View File

@@ -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();
}
}

View File

@@ -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);
}

View File

@@ -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();
}
}

View File

@@ -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();

View File

@@ -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)));
}

View File

@@ -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<ScriptFile> {
@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();
}
}
}

View File

@@ -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<PFile, Boolean> 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<ExplorerItem, Boolean> mFilter;
private OnItemOperatedListener mOnItemOperatedListener;
protected ExplorerItem mSelectedItem;
private Explorer mExplorer;
private Stack<ExplorerPageState> 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<PFile, Boolean> filter) {
public void setFilter(Function<ExplorerItem, Boolean> 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<BindableViewHolder<?>> {
private class ExplorerAdapter extends RecyclerView.Adapter<BindableViewHolder<?>> {
@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<ScriptFile> {
protected class ExplorerItemViewHolder extends BindableViewHolder<ExplorerItem> {
@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<ScriptFile> {
protected class ExplorerPageViewHolder extends BindableViewHolder<ExplorerPage> {
@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;
}
}
}

View File

@@ -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;

View File

@@ -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<File> 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();
}
});
}

View File

@@ -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()),

View File

@@ -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<ScriptFile> mScriptFiles = new ArrayList<>();
private ArrayList<ScriptFile> mDirectories = new ArrayList<>();
private ArrayList<ExplorerItem> mItems = new ArrayList<>();
private ArrayList<ExplorerPage> mItemGroups = new ArrayList<>();
public boolean isDirSortedAscending() {
@@ -111,66 +110,66 @@ public class ScriptList {
mSortConfig.mFileSortedAscending = fileSortedAscending;
}
private Comparator<File> getComparator(int sortType) {
private Comparator<ExplorerItem> 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;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@@ -24,7 +24,7 @@
</com.stardust.theme.widget.ThemeColorToolbar>
</android.support.design.widget.AppBarLayout>
<org.autojs.autojs.ui.main.scripts.ScriptListView
<org.autojs.autojs.ui.main.scripts.ExplorerView
android:id="@+id/script_list"
android:layout_width="match_parent"
android:layout_height="match_parent"

View File

@@ -49,7 +49,7 @@
android:textSize="16sp"/>
</LinearLayout>
<org.autojs.autojs.ui.main.scripts.ScriptListView
<org.autojs.autojs.ui.main.scripts.ExplorerView
android:id="@+id/script_list"
android:layout_width="match_parent"
android:layout_height="match_parent"

View File

@@ -4,10 +4,6 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<org.autojs.autojs.ui.main.sample.SampleListView
android:id="@+id/sample_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</FrameLayout>

View File

@@ -4,7 +4,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<org.autojs.autojs.ui.main.scripts.ScriptListView
<org.autojs.autojs.ui.main.scripts.ExplorerView
android:id="@+id/script_file_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>

View File

@@ -21,13 +21,12 @@
android:paddingTop="16dp">
<ImageView
android:id="@+id/icon"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_vertical"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:src="@drawable/ic_folder_yellow_100px"
android:tint="#ffda93"/>
android:layout_marginRight="16dp"/>
<TextView
android:id="@+id/name"

View File

@@ -266,7 +266,7 @@
<string name="text_registering">注册中</string>
<string name="text_register_fail">注册失败</string>
<string name="text_register_succeed">注册成功</string>
<string name="text_sample">示例</string>
<string name="text_sample">示例代码</string>
<string name="text_copy_to_my_script">导入到我的脚本</string>
<string name="text_reset_to_initial_content">重置为初始内容</string>
<string name="text_reset_fail">重置失败</string>

View File

@@ -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++){

View File

@@ -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

View File

@@ -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);
}

View File

@@ -35,7 +35,7 @@ public class RootAutomatorEngine extends ScriptEngine.AbstractScriptEngine<AutoF
private static final String ROOT_AUTOMATOR_EXECUTABLE_ASSET = "binary/root_automator";
private Context mContext;
private String mDeviceNameOrPath;
private final String mDeviceNameOrPath;
private Thread mThread;
private String mExecutablePath;
private String mPid;

View File

@@ -1 +1 @@
[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":415},"path":"commonRelease-4.0.2 Alpha10.apk","properties":{"packageId":"org.autojs.autojs","split":"","minSdkVersion":"17"}}]
[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":416},"path":"commonRelease-4.0.2 Alpha11.apk","properties":{"packageId":"org.autojs.autojs","split":"","minSdkVersion":"17"}}]