Added Script file chooser. Fixed the issue that background image setting not working
This commit is contained in:
@@ -13,8 +13,6 @@ import com.stardust.scriptdroid.autojs.AutoJs;
|
||||
public class Pref {
|
||||
|
||||
private static final SharedPreferences DISPOSABLE_BOOLEAN = App.getApp().getSharedPreferences("DISPOSABLE_BOOLEAN", Context.MODE_PRIVATE);
|
||||
public static final String KEY_DRAWER_HEADER_IMAGE_PATH = "KEY_DRAWER_HEADER_IMAGE_PATH";
|
||||
public static final String KEY_APP_BAR_IMAGE_PATH = "KEY_APP_BAR_IMAGE_PATH";
|
||||
private static SharedPreferences.OnSharedPreferenceChangeListener onSharedPreferenceChangeListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||
@@ -84,22 +82,6 @@ public class Pref {
|
||||
return getDisposableBoolean("isFirstUsing", true);
|
||||
}
|
||||
|
||||
public static String getDrawerHeaderImagePath() {
|
||||
return def().getString(KEY_DRAWER_HEADER_IMAGE_PATH, null);
|
||||
}
|
||||
|
||||
public static void setDrawerHeaderImagePath(String path) {
|
||||
def().edit().putString(KEY_DRAWER_HEADER_IMAGE_PATH, path).apply();
|
||||
}
|
||||
|
||||
public static String getAppBarImagePath() {
|
||||
return def().getString(KEY_APP_BAR_IMAGE_PATH, null);
|
||||
}
|
||||
|
||||
public static void setAppBarImagePath(String path) {
|
||||
def().edit().putString(KEY_APP_BAR_IMAGE_PATH, path).apply();
|
||||
}
|
||||
|
||||
static {
|
||||
def().registerOnSharedPreferenceChangeListener(onSharedPreferenceChangeListener);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.stardust.scriptdroid.external;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/4/1.
|
||||
*/
|
||||
@@ -10,5 +12,8 @@ public class CommonUtils {
|
||||
|
||||
public static final String EXTRA_KEY_PREPARE_SCRIPT = "script";
|
||||
|
||||
public static boolean isTaskerBundleValid(Bundle bundle) {
|
||||
return bundle.containsKey(CommonUtils.EXTRA_KEY_PATH);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,19 +23,16 @@ public class FireSettingReceiver extends AbstractPluginSettingReceiver {
|
||||
|
||||
@Override
|
||||
protected boolean isBundleValid(@NonNull Bundle bundle) {
|
||||
Log.v(TAG, "isBundleValid: " + bundle);
|
||||
return bundle.containsKey(CommonUtils.EXTRA_KEY_PATH);
|
||||
return CommonUtils.isTaskerBundleValid(bundle);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isAsync() {
|
||||
Log.v(TAG, "isAsync");
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void firePluginSetting(@NonNull Context context, @NonNull Bundle bundle) {
|
||||
Log.v(TAG, "firePluginSetting:" + bundle);
|
||||
context.startActivity(new Intent(App.getApp(), RunIntentActivity.class)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
.putExtra(CommonUtils.EXTRA_KEY_PATH, bundle.getString(CommonUtils.EXTRA_KEY_PATH))
|
||||
|
||||
@@ -9,7 +9,8 @@ import android.util.Log;
|
||||
import com.stardust.scriptdroid.scripts.ScriptFile;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.external.CommonUtils;
|
||||
import com.stardust.scriptdroid.ui.main.my_script_list.ScriptAndFolderListRecyclerView;
|
||||
import com.stardust.scriptdroid.ui.main.script_list.ScriptAndFolderListRecyclerView;
|
||||
import com.stardust.scriptdroid.ui.main.script_list.ScriptListWithProgressBarView;
|
||||
import com.twofortyfouram.locale.sdk.client.ui.activity.AbstractPluginActivity;
|
||||
|
||||
/**
|
||||
@@ -18,20 +19,19 @@ import com.twofortyfouram.locale.sdk.client.ui.activity.AbstractPluginActivity;
|
||||
|
||||
public class TaskPrefEditActivity extends AbstractPluginActivity {
|
||||
|
||||
private static final String TAG = "TaskPrefEditActivity";
|
||||
private String mSelectedScriptFilePath;
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
Log.v(TAG, "onCreate");
|
||||
setContentView(R.layout.activity_tasker_edit);
|
||||
initScriptListRecyclerView();
|
||||
}
|
||||
|
||||
private void initScriptListRecyclerView() {
|
||||
ScriptAndFolderListRecyclerView scriptListRecyclerView = (ScriptAndFolderListRecyclerView) findViewById(R.id.script_list);
|
||||
scriptListRecyclerView.setOnItemClickListener(new ScriptAndFolderListRecyclerView.OnScriptFileClickListener() {
|
||||
ScriptListWithProgressBarView scriptListWithProgressBarView = (ScriptListWithProgressBarView) findViewById(R.id.script_list);
|
||||
scriptListWithProgressBarView.setScriptFileOperationEnabled(false);
|
||||
scriptListWithProgressBarView.setOnItemClickListener(new ScriptAndFolderListRecyclerView.OnScriptFileClickListener() {
|
||||
@Override
|
||||
public void onClick(ScriptFile file) {
|
||||
mSelectedScriptFilePath = file.getPath();
|
||||
@@ -43,22 +43,17 @@ public class TaskPrefEditActivity extends AbstractPluginActivity {
|
||||
|
||||
@Override
|
||||
public boolean isBundleValid(@NonNull Bundle bundle) {
|
||||
boolean valid = bundle.getString(CommonUtils.EXTRA_KEY_PATH) != null;
|
||||
Log.v(TAG, "isBundleValid: " + valid);
|
||||
Context context;
|
||||
return valid;
|
||||
return CommonUtils.isTaskerBundleValid(bundle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPostCreateWithPreviousResult(@NonNull Bundle bundle, @NonNull String s) {
|
||||
Log.v(TAG, "onPostCreateWithPreviousResult: bundle=" + bundle + " str=" + s);
|
||||
mSelectedScriptFilePath = bundle.getString(CommonUtils.EXTRA_KEY_PATH);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Bundle getResultBundle() {
|
||||
Log.v(TAG, "getResultBundle");
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(CommonUtils.EXTRA_KEY_PATH, mSelectedScriptFilePath);
|
||||
return bundle;
|
||||
@@ -67,7 +62,6 @@ public class TaskPrefEditActivity extends AbstractPluginActivity {
|
||||
@NonNull
|
||||
@Override
|
||||
public String getResultBlurb(@NonNull Bundle bundle) {
|
||||
Log.v(TAG, "getResultBlurb");
|
||||
return bundle.getString(CommonUtils.EXTRA_KEY_PATH, getString(R.string.text_path_is_empty));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,7 +178,7 @@ public class LayoutHierarchyView extends MultiLevelListView {
|
||||
NodeInfo nodeInfo = (NodeInfo) object;
|
||||
ViewHolder viewHolder;
|
||||
if (convertView == null) {
|
||||
convertView = LayoutInflater.from(getContext()).inflate(R.layout.layout_hierarchy_view_item, null);
|
||||
convertView = LayoutInflater.from(getContext()).inflate(R.layout.layout_hierarchy_view_item, LayoutHierarchyView.this, false);
|
||||
viewHolder = new ViewHolder(convertView);
|
||||
convertView.setTag(viewHolder);
|
||||
} else {
|
||||
|
||||
@@ -6,9 +6,12 @@ import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.util.FileSorter;
|
||||
import com.stardust.util.LimitedHashMap;
|
||||
import com.stardust.util.MapEntries;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/31.
|
||||
*/
|
||||
@@ -29,11 +32,19 @@ public class StorageScriptProvider {
|
||||
public static final ScriptFile DEFAULT_DIRECTORY = new ScriptFile(DEFAULT_DIRECTORY_PATH);
|
||||
|
||||
|
||||
|
||||
private static StorageScriptProvider instance = new StorageScriptProvider();
|
||||
private static StorageScriptProvider defaultProvider = new StorageScriptProvider();
|
||||
|
||||
public static StorageScriptProvider getDefault() {
|
||||
return instance;
|
||||
return defaultProvider;
|
||||
}
|
||||
|
||||
private static StorageScriptProvider externalStorageProvider;
|
||||
|
||||
public static StorageScriptProvider getExternalStorageProvider() {
|
||||
if (externalStorageProvider == null) {
|
||||
externalStorageProvider = new StorageScriptProvider(Environment.getExternalStorageDirectory().getPath(), 5);
|
||||
}
|
||||
return externalStorageProvider;
|
||||
}
|
||||
|
||||
private EventBus mDirectoryEventBus = new EventBus();
|
||||
@@ -47,7 +58,6 @@ public class StorageScriptProvider {
|
||||
|
||||
public StorageScriptProvider(ScriptFile initialDirectory, int cacheSize) {
|
||||
mInitialDirectory = initialDirectory;
|
||||
mInitialDirectoryScriptFiles = getInitialDirectoryScriptFilesInner();
|
||||
mScriptFileCache = new LimitedHashMap<>(cacheSize);
|
||||
}
|
||||
|
||||
@@ -57,7 +67,7 @@ public class StorageScriptProvider {
|
||||
|
||||
public void notifyDirectoryChanged(ScriptFile directory) {
|
||||
if (directory.equals(mInitialDirectory)) {
|
||||
mInitialDirectoryScriptFiles = getInitialDirectoryScriptFilesInner();
|
||||
mInitialDirectoryScriptFiles = getInitialDirectoryScriptFiles();
|
||||
} else {
|
||||
clearCache(directory);
|
||||
}
|
||||
@@ -66,15 +76,28 @@ public class StorageScriptProvider {
|
||||
|
||||
public void notifyStoragePermissionGranted() {
|
||||
mScriptFileCache.clear();
|
||||
mInitialDirectoryScriptFiles = getInitialDirectoryScriptFilesInner();
|
||||
mInitialDirectoryScriptFiles = null;
|
||||
mDirectoryEventBus.post(new DirectoryChangeEvent(mInitialDirectory));
|
||||
}
|
||||
|
||||
public void refreshAll() {
|
||||
Map<String, ScriptFile> files = (Map<String, ScriptFile>) mScriptFileCache.clone();
|
||||
mScriptFileCache.clear();
|
||||
mInitialDirectoryScriptFiles = null;
|
||||
mDirectoryEventBus.post(new DirectoryChangeEvent(mInitialDirectory));
|
||||
for (Map.Entry<String, ScriptFile> file : files.entrySet()) {
|
||||
mDirectoryEventBus.post(new DirectoryChangeEvent(new ScriptFile(file.getKey())));
|
||||
}
|
||||
}
|
||||
|
||||
public ScriptFile getInitialDirectory() {
|
||||
return mInitialDirectory;
|
||||
}
|
||||
|
||||
public ScriptFile[] getInitialDirectoryScriptFiles() {
|
||||
if (mInitialDirectoryScriptFiles == null) {
|
||||
mInitialDirectoryScriptFiles = getInitialDirectoryScriptFilesInner();
|
||||
}
|
||||
return mInitialDirectoryScriptFiles;
|
||||
}
|
||||
|
||||
@@ -84,7 +107,7 @@ public class StorageScriptProvider {
|
||||
|
||||
public ScriptFile[] getDirectoryScriptFiles(ScriptFile directory) {
|
||||
if (directory.equals(mInitialDirectory)) {
|
||||
return mInitialDirectoryScriptFiles;
|
||||
return getInitialDirectoryScriptFiles();
|
||||
}
|
||||
ScriptFile[] scriptFiles = getScriptFilesFromCache(directory);
|
||||
if (scriptFiles == null) {
|
||||
@@ -93,6 +116,10 @@ public class StorageScriptProvider {
|
||||
return scriptFiles;
|
||||
}
|
||||
|
||||
public void clearCacheExceptInitialDirectory() {
|
||||
mScriptFileCache.clear();
|
||||
}
|
||||
|
||||
private void clearCache(ScriptFile directory) {
|
||||
mScriptFileCache.remove(directory.getPath());
|
||||
}
|
||||
@@ -119,7 +146,8 @@ public class StorageScriptProvider {
|
||||
|
||||
|
||||
public void registerDirectoryChangeListener(Object subscriber) {
|
||||
mDirectoryEventBus.register(subscriber);
|
||||
if (!mDirectoryEventBus.isRegistered(subscriber))
|
||||
mDirectoryEventBus.register(subscriber);
|
||||
}
|
||||
|
||||
public void unregisterDirectoryChangeListener(Object subscriber) {
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
package com.stardust.scriptdroid.tool;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.stardust.app.OnActivityResultDelegate;
|
||||
import com.stardust.pio.PFile;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/4/3.
|
||||
*/
|
||||
|
||||
public abstract class DrawableSaver {
|
||||
|
||||
private static final String PREFIX = "saved_drawable_";
|
||||
|
||||
protected Drawable mOriginalDrawble;
|
||||
private Context mContext;
|
||||
private String mName;
|
||||
|
||||
public DrawableSaver(Context context, String name, Drawable originalDrawble) {
|
||||
mContext = context;
|
||||
mName = PREFIX + name;
|
||||
mOriginalDrawble = originalDrawble;
|
||||
readImageAndApply();
|
||||
}
|
||||
|
||||
private void readImageAndApply() {
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
InputStream inputStream = mContext.openFileInput(mName);
|
||||
Drawable drawable = BitmapDrawable.createFromStream(inputStream, mName);
|
||||
applyDrawableToView(drawable);
|
||||
} catch (FileNotFoundException e) {
|
||||
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
public void setDrawable(InputStream inputStream) {
|
||||
saveDrawable(inputStream, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
readImageAndApply();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void saveDrawable(final InputStream inputStream, final Runnable callback) {
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
OutputStream outputStream = mContext.openFileOutput(mName, Context.MODE_PRIVATE);
|
||||
PFile.write(inputStream, outputStream);
|
||||
outputStream.close();
|
||||
inputStream.close();
|
||||
callback.run();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
|
||||
}
|
||||
|
||||
public void select(Activity activity, final OnActivityResultDelegate.Intermediary intermediary) {
|
||||
new ImageSelector(activity, intermediary, new ImageSelector.ImageSelectorCallback() {
|
||||
@Override
|
||||
public void onImageSelected(ImageSelector selector, InputStream inputStream) {
|
||||
if (inputStream != null)
|
||||
setDrawable(inputStream);
|
||||
intermediary.removeDelegate(selector);
|
||||
}
|
||||
}).select();
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
applyDrawableToView(mOriginalDrawble);
|
||||
mContext.deleteFile(mName);
|
||||
}
|
||||
|
||||
public static void reset(Context context, String name) {
|
||||
context.deleteFile(PREFIX + name);
|
||||
}
|
||||
|
||||
protected abstract void applyDrawableToView(Drawable drawable);
|
||||
|
||||
public static class ViewBackgroundSaver extends DrawableSaver {
|
||||
|
||||
private View mView;
|
||||
|
||||
public ViewBackgroundSaver(Context activity, String name, View view) {
|
||||
super(activity, name, view.getBackground());
|
||||
mView = view;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyDrawableToView(final Drawable drawable) {
|
||||
mView.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mView.setBackground(drawable);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public static class ImageSaver extends DrawableSaver {
|
||||
|
||||
private ImageView mView;
|
||||
|
||||
public ImageSaver(Context activity, String name, ImageView view) {
|
||||
super(activity, name, view.getDrawable());
|
||||
mView = view;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyDrawableToView(final Drawable drawable) {
|
||||
mView.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mView.setImageDrawable(drawable);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,9 @@ import android.provider.MediaStore;
|
||||
import com.stardust.app.OnActivityResultDelegate;
|
||||
import com.stardust.scriptdroid.R;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/5.
|
||||
*/
|
||||
@@ -16,7 +19,7 @@ import com.stardust.scriptdroid.R;
|
||||
public class ImageSelector implements OnActivityResultDelegate {
|
||||
|
||||
public interface ImageSelectorCallback {
|
||||
void onImageSelected(ImageSelector selector, String path);
|
||||
void onImageSelected(ImageSelector selector, InputStream path);
|
||||
}
|
||||
|
||||
private static final int REQUEST_CODE = "LOVE EATING".hashCode() >> 16;
|
||||
@@ -38,19 +41,16 @@ public class ImageSelector implements OnActivityResultDelegate {
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (data == null)
|
||||
if (data == null) {
|
||||
mCallback.onImageSelected(this, null);
|
||||
return;
|
||||
Uri selectedImageUri = data.getData();
|
||||
String[] filePathColumn = {MediaStore.Images.Media.DATA};
|
||||
Cursor cursor = mActivity.getContentResolver().query(selectedImageUri, filePathColumn, null, null, null);
|
||||
if (cursor != null) {
|
||||
cursor.moveToFirst();
|
||||
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
|
||||
String filePath = cursor.getString(columnIndex);
|
||||
cursor.close();
|
||||
mCallback.onImageSelected(this, filePath);
|
||||
}
|
||||
|
||||
try {
|
||||
InputStream inputStream = mActivity.getContentResolver().openInputStream(data.getData());
|
||||
mCallback.onImageSelected(this, inputStream);
|
||||
} catch (FileNotFoundException e) {
|
||||
mCallback.onImageSelected(this, null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||
* Created by Stardust on 2017/1/23.
|
||||
*/
|
||||
|
||||
public class BaseActivity extends AppCompatActivity {
|
||||
public abstract class BaseActivity extends AppCompatActivity {
|
||||
|
||||
protected static final int PERMISSION_REQUEST_CODE = 11186;
|
||||
private BackPressedHandler.Observer mBackPressObserver = new BackPressedHandler.Observer();
|
||||
|
||||
@@ -17,7 +17,7 @@ import java.util.Map;
|
||||
/**
|
||||
* Created by Stardust on 2017/1/30.
|
||||
*/
|
||||
public class Editor920Activity extends IActivity {
|
||||
public abstract class Editor920Activity extends IActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
|
||||
@@ -0,0 +1,642 @@
|
||||
package com.stardust.scriptdroid.ui.error;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.StringDef;
|
||||
import android.support.annotation.StringRes;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.support.design.widget.TextInputEditText;
|
||||
import android.support.design.widget.TextInputLayout;
|
||||
import android.support.v4.app.NavUtils;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RadioButton;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.afollestad.materialdialogs.DialogAction;
|
||||
import com.afollestad.materialdialogs.MaterialDialog;
|
||||
import com.github.aakira.expandablelayout.ExpandableRelativeLayout;
|
||||
import com.heinrichreimersoftware.androidissuereporter.model.DeviceInfo;
|
||||
import com.heinrichreimersoftware.androidissuereporter.model.Report;
|
||||
import com.heinrichreimersoftware.androidissuereporter.model.github.ExtraInfo;
|
||||
import com.heinrichreimersoftware.androidissuereporter.model.github.GithubLogin;
|
||||
import com.heinrichreimersoftware.androidissuereporter.model.github.GithubTarget;
|
||||
import com.heinrichreimersoftware.androidissuereporter.util.ColorUtils;
|
||||
import com.heinrichreimersoftware.androidissuereporter.util.ThemeUtils;
|
||||
|
||||
import org.eclipse.egit.github.core.Issue;
|
||||
import org.eclipse.egit.github.core.client.GitHubClient;
|
||||
import org.eclipse.egit.github.core.client.RequestException;
|
||||
import org.eclipse.egit.github.core.service.IssueService;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import static android.util.Patterns.EMAIL_ADDRESS;
|
||||
|
||||
import com.heinrichreimersoftware.androidissuereporter.R;
|
||||
import com.stardust.theme.ThemeColorManager;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/4/3.
|
||||
*/
|
||||
|
||||
public abstract class AbstractIssueReporterActivity extends AppCompatActivity {
|
||||
|
||||
private static final String TAG = AbstractIssueReporterActivity.class.getSimpleName();
|
||||
|
||||
private static final int STATUS_BAD_CREDENTIALS = 401;
|
||||
private static final int STATUS_ISSUES_NOT_ENABLED = 410;
|
||||
private boolean mCrash = false;
|
||||
private boolean mReportFailed = true;
|
||||
|
||||
@StringDef({RESULT_OK, RESULT_BAD_CREDENTIALS, RESULT_INVALID_TOKEN, RESULT_ISSUES_NOT_ENABLED,
|
||||
RESULT_UNKNOWN})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
private @interface Result {
|
||||
}
|
||||
|
||||
private static final String RESULT_OK = "RESULT_OK";
|
||||
private static final String RESULT_BAD_CREDENTIALS = "RESULT_BAD_CREDENTIALS";
|
||||
private static final String RESULT_INVALID_TOKEN = "RESULT_INVALID_TOKEN";
|
||||
private static final String RESULT_ISSUES_NOT_ENABLED = "RESULT_ISSUES_NOT_ENABLED";
|
||||
private static final String RESULT_UNKNOWN = "RESULT_UNKNOWN";
|
||||
private boolean emailRequired = false;
|
||||
private int bodyMinChar = 0;
|
||||
private Toolbar toolbar;
|
||||
private TextInputEditText inputTitle;
|
||||
private TextInputEditText inputDescription;
|
||||
private TextView textDeviceInfo;
|
||||
private ImageButton buttonDeviceInfo;
|
||||
private ExpandableRelativeLayout layoutDeviceInfo;
|
||||
private ExpandableRelativeLayout layoutAnonymous;
|
||||
private TextInputEditText inputUsername;
|
||||
private TextInputEditText inputPassword;
|
||||
private TextInputEditText inputEmail;
|
||||
private RadioButton optionUseAccount;
|
||||
private RadioButton optionAnonymous;
|
||||
private ExpandableRelativeLayout layoutLogin;
|
||||
private FloatingActionButton buttonSend;
|
||||
|
||||
private Drawable optionUseAccountButtonDrawable = null;
|
||||
|
||||
private String token;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
if (TextUtils.isEmpty(getTitle()))
|
||||
setTitle(R.string.air_title_report_issue);
|
||||
|
||||
setContentView(com.stardust.scriptdroid.R.layout.air_activity_issue_reporter);
|
||||
findViews();
|
||||
|
||||
//noinspection deprecation
|
||||
token = getGuestToken();
|
||||
|
||||
initViews();
|
||||
|
||||
|
||||
DeviceInfo deviceInfo = new DeviceInfo(this);
|
||||
textDeviceInfo.setText(deviceInfo.toString());
|
||||
|
||||
handleIntent();
|
||||
|
||||
optionAnonymous.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
optionAnonymous.performClick();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void handleIntent() {
|
||||
final String errorDetail = getIntent().getStringExtra("error");
|
||||
if (errorDetail != null) {
|
||||
inputDescription.setText(errorDetail);
|
||||
String title = getFirstLine(errorDetail);
|
||||
inputTitle.setText(title);
|
||||
mCrash = true;
|
||||
}
|
||||
}
|
||||
|
||||
private String getFirstLine(String str) {
|
||||
int i = str.indexOf('\n');
|
||||
if (i < 0)
|
||||
return str;
|
||||
return str.substring(0, i);
|
||||
}
|
||||
|
||||
private void findViews() {
|
||||
toolbar = (Toolbar) findViewById(R.id.air_toolbar);
|
||||
|
||||
inputTitle = (TextInputEditText) findViewById(R.id.air_inputTitle);
|
||||
inputDescription = (TextInputEditText) findViewById(R.id.air_inputDescription);
|
||||
textDeviceInfo = (TextView) findViewById(R.id.air_textDeviceInfo);
|
||||
buttonDeviceInfo = (ImageButton) findViewById(R.id.air_buttonDeviceInfo);
|
||||
layoutDeviceInfo = (ExpandableRelativeLayout) findViewById(R.id.air_layoutDeviceInfo);
|
||||
|
||||
inputUsername = (TextInputEditText) findViewById(R.id.air_inputUsername);
|
||||
inputPassword = (TextInputEditText) findViewById(R.id.air_inputPassword);
|
||||
inputEmail = (TextInputEditText) findViewById(R.id.air_inputEmail);
|
||||
optionUseAccount = (RadioButton) findViewById(R.id.air_optionUseAccount);
|
||||
optionAnonymous = (RadioButton) findViewById(R.id.air_optionAnonymous);
|
||||
layoutLogin = (ExpandableRelativeLayout) findViewById(R.id.air_layoutLogin);
|
||||
layoutAnonymous = (ExpandableRelativeLayout) findViewById(R.id.air_layoutGuest);
|
||||
|
||||
buttonSend = (FloatingActionButton) findViewById(R.id.air_buttonSend);
|
||||
}
|
||||
|
||||
private void initViews() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
getWindow().setStatusBarColor(ThemeColorManager.getColorPrimary());
|
||||
}
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
actionBar.setTitle(com.stardust.scriptdroid.R.string.text_issue_report);
|
||||
}
|
||||
toolbar.setBackgroundColor(ThemeColorManager.getColorPrimary());
|
||||
|
||||
|
||||
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
finish();
|
||||
}
|
||||
});
|
||||
|
||||
buttonDeviceInfo.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
layoutDeviceInfo.toggle();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
inputPassword.setOnEditorActionListener(new TextView.OnEditorActionListener() {
|
||||
@Override
|
||||
public boolean onEditorAction(TextView textView, int actionId, KeyEvent event) {
|
||||
if (actionId == EditorInfo.IME_ACTION_SEND) {
|
||||
reportIssue();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
updateGuestTokenViews();
|
||||
|
||||
buttonSend.setImageResource(ColorUtils.isDark(ThemeUtils.getColorAccent(this)) ?
|
||||
R.drawable.air_ic_send_dark : R.drawable.air_ic_send_light);
|
||||
buttonSend.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
try {
|
||||
reportIssue();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
mReportFailed = true;
|
||||
finish();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private void setOptionUseAccountMarginStart(int marginStart) {
|
||||
LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) optionUseAccount.getLayoutParams();
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
layoutParams.setMarginStart(marginStart);
|
||||
} else {
|
||||
layoutParams.leftMargin = marginStart;
|
||||
}
|
||||
optionUseAccount.setLayoutParams(layoutParams);
|
||||
}
|
||||
|
||||
private void updateGuestTokenViews() {
|
||||
if (TextUtils.isEmpty(token)) {
|
||||
int baseline = getResources().getDimensionPixelSize(R.dimen.air_baseline);
|
||||
int radioButtonPaddingStart = getResources().getDimensionPixelSize(R.dimen.air_radio_button_padding_start);
|
||||
setOptionUseAccountMarginStart(-2 * baseline - radioButtonPaddingStart);
|
||||
optionUseAccount.setEnabled(false);
|
||||
optionAnonymous.setVisibility(View.GONE);
|
||||
} else {
|
||||
setOptionUseAccountMarginStart(0);
|
||||
optionUseAccount.setEnabled(true);
|
||||
optionUseAccount.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
layoutLogin.expand();
|
||||
layoutAnonymous.collapse();
|
||||
inputUsername.setEnabled(true);
|
||||
inputPassword.setEnabled(true);
|
||||
}
|
||||
});
|
||||
optionAnonymous.setVisibility(View.VISIBLE);
|
||||
optionAnonymous.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
layoutLogin.collapse();
|
||||
layoutAnonymous.expand();
|
||||
inputUsername.setEnabled(false);
|
||||
inputPassword.setEnabled(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void reportIssue() {
|
||||
|
||||
if (!validateInput()) return;
|
||||
|
||||
if (optionUseAccount.isChecked()) {
|
||||
String username = inputUsername.getText().toString();
|
||||
String password = inputPassword.getText().toString();
|
||||
sendBugReport(new GithubLogin(username, password), null);
|
||||
} else {
|
||||
if (TextUtils.isEmpty(token))
|
||||
throw new IllegalStateException("You must provide a GitHub API Token.");
|
||||
|
||||
String email = null;
|
||||
if (!TextUtils.isEmpty(inputEmail.getText()) &&
|
||||
EMAIL_ADDRESS.matcher(inputEmail.getText().toString()).matches()) {
|
||||
email = inputEmail.getText().toString();
|
||||
}
|
||||
|
||||
sendBugReport(new GithubLogin(token), email);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean validateInput() {
|
||||
boolean hasErrors = false;
|
||||
|
||||
if (optionUseAccount.isChecked()) {
|
||||
if (TextUtils.isEmpty(inputUsername.getText())) {
|
||||
setError(inputUsername, R.string.air_error_no_username);
|
||||
hasErrors = true;
|
||||
} else {
|
||||
removeError(inputUsername);
|
||||
}
|
||||
|
||||
if (TextUtils.isEmpty(inputPassword.getText())) {
|
||||
setError(inputPassword, R.string.air_error_no_password);
|
||||
hasErrors = true;
|
||||
} else {
|
||||
removeError(inputPassword);
|
||||
}
|
||||
} else {
|
||||
if (emailRequired) {
|
||||
if (TextUtils.isEmpty(inputEmail.getText()) ||
|
||||
!EMAIL_ADDRESS.matcher(inputEmail.getText().toString()).matches()) {
|
||||
setError(inputEmail, R.string.air_error_no_email);
|
||||
hasErrors = true;
|
||||
} else {
|
||||
removeError(inputEmail);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (TextUtils.isEmpty(inputTitle.getText())) {
|
||||
setError(inputTitle, R.string.air_error_no_title);
|
||||
hasErrors = true;
|
||||
} else {
|
||||
removeError(inputTitle);
|
||||
}
|
||||
|
||||
if (TextUtils.isEmpty(inputDescription.getText())) {
|
||||
setError(inputDescription, R.string.air_error_no_description);
|
||||
hasErrors = true;
|
||||
} else {
|
||||
if (bodyMinChar > 0) {
|
||||
if (inputDescription.getText().toString().length() < bodyMinChar) {
|
||||
setError(inputDescription, getResources().getQuantityString(R.plurals.air_error_short_description, bodyMinChar, bodyMinChar));
|
||||
hasErrors = true;
|
||||
} else {
|
||||
removeError(inputDescription);
|
||||
}
|
||||
} else
|
||||
removeError(inputDescription);
|
||||
}
|
||||
return !hasErrors;
|
||||
}
|
||||
|
||||
private void setError(TextInputEditText editText, @StringRes int errorRes) {
|
||||
try {
|
||||
View layout = (View) editText.getParent();
|
||||
while (!layout.getClass().getSimpleName().equals(TextInputLayout.class.getSimpleName()))
|
||||
layout = (View) layout.getParent();
|
||||
TextInputLayout realLayout = (TextInputLayout) layout;
|
||||
realLayout.setError(getString(errorRes));
|
||||
} catch (ClassCastException | NullPointerException e) {
|
||||
Log.e(TAG, "Issue while setting error UI.", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void setError(TextInputEditText editText, String error) {
|
||||
try {
|
||||
View layout = (View) editText.getParent();
|
||||
while (!layout.getClass().getSimpleName().equals(TextInputLayout.class.getSimpleName()))
|
||||
layout = (View) layout.getParent();
|
||||
TextInputLayout realLayout = (TextInputLayout) layout;
|
||||
realLayout.setError(error);
|
||||
} catch (ClassCastException | NullPointerException e) {
|
||||
Log.e(TAG, "Issue while setting error UI.", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void removeError(TextInputEditText editText) {
|
||||
try {
|
||||
View layout = (View) editText.getParent();
|
||||
while (!layout.getClass().getSimpleName().equals(TextInputLayout.class.getSimpleName()))
|
||||
layout = (View) layout.getParent();
|
||||
TextInputLayout realLayout = (TextInputLayout) layout;
|
||||
realLayout.setError(null);
|
||||
} catch (ClassCastException | NullPointerException e) {
|
||||
Log.e(TAG, "Issue while removing error UI.", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void sendBugReport(GithubLogin login, String email) {
|
||||
if (!validateInput()) return;
|
||||
|
||||
String bugTitle = inputTitle.getText().toString();
|
||||
String bugDescription = inputDescription.getText().toString();
|
||||
|
||||
DeviceInfo deviceInfo = new DeviceInfo(this);
|
||||
|
||||
ExtraInfo extraInfo = new ExtraInfo();
|
||||
onSaveExtraInfo(extraInfo);
|
||||
|
||||
Report report = new Report(bugTitle, bugDescription, deviceInfo, extraInfo, email);
|
||||
GithubTarget target = getTarget();
|
||||
|
||||
report(this, report, target, login);
|
||||
}
|
||||
|
||||
protected final void setGuestEmailRequired(boolean required) {
|
||||
this.emailRequired = required;
|
||||
if (required) {
|
||||
optionAnonymous.setText(R.string.air_label_use_email);
|
||||
((TextInputLayout) findViewById(R.id.air_inputEmailParent)).setHint(getString(R.string.air_label_email));
|
||||
} else {
|
||||
optionAnonymous.setText(R.string.air_label_use_guest);
|
||||
((TextInputLayout) findViewById(R.id.air_inputEmailParent)).setHint(getString(R.string.air_label_email_optional));
|
||||
}
|
||||
}
|
||||
|
||||
protected final void setMinimumDescriptionLength(int length) {
|
||||
this.bodyMinChar = length;
|
||||
}
|
||||
|
||||
protected void onSaveExtraInfo(ExtraInfo extraInfo) {
|
||||
}
|
||||
|
||||
protected abstract GithubTarget getTarget();
|
||||
|
||||
@Deprecated
|
||||
protected String getGuestToken() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected final void setGuestToken(String token) {
|
||||
this.token = token;
|
||||
Log.d(TAG, "GuestToken: " + token);
|
||||
updateGuestTokenViews();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish() {
|
||||
if (mCrash) {
|
||||
if (!mReportFailed) {
|
||||
Toast.makeText(this, com.stardust.scriptdroid.R.string.text_report_succeed, Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
Toast.makeText(this, com.stardust.scriptdroid.R.string.text_report_fail, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
finishAffinity();
|
||||
} else {
|
||||
super.finish();
|
||||
}
|
||||
}
|
||||
|
||||
private void report(Activity activity, Report report, GithubTarget target,
|
||||
GithubLogin login) {
|
||||
new ReportIssueTask(activity, report, target, login).execute();
|
||||
}
|
||||
|
||||
private class ReportIssueTask extends DialogAsyncTask<Void, Void, String> {
|
||||
private final Report report;
|
||||
private final GithubTarget target;
|
||||
private final GithubLogin login;
|
||||
|
||||
private ReportIssueTask(Activity activity, Report report, GithubTarget target,
|
||||
GithubLogin login) {
|
||||
super(activity);
|
||||
this.report = report;
|
||||
this.target = target;
|
||||
this.login = login;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Dialog createDialog(@NonNull Context context) {
|
||||
return new MaterialDialog.Builder(context)
|
||||
.progress(true, 0)
|
||||
.progressIndeterminateStyle(true)
|
||||
.title(R.string.air_dialog_title_loading)
|
||||
.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Result
|
||||
protected String doInBackground(Void... params) {
|
||||
GitHubClient client;
|
||||
if (login.shouldUseApiToken()) {
|
||||
client = new GitHubClient().setOAuth2Token(login.getApiToken());
|
||||
} else {
|
||||
client = new GitHubClient().setCredentials(login.getUsername(), login.getPassword());
|
||||
}
|
||||
|
||||
Issue issue = new Issue().setTitle(report.getTitle()).setBody(report.getDescription());
|
||||
try {
|
||||
new IssueService(client).createIssue(target.getUsername(), target.getRepository(), issue);
|
||||
return RESULT_OK;
|
||||
} catch (RequestException e) {
|
||||
switch (e.getStatus()) {
|
||||
case STATUS_BAD_CREDENTIALS:
|
||||
if (login.shouldUseApiToken())
|
||||
return RESULT_INVALID_TOKEN;
|
||||
return RESULT_BAD_CREDENTIALS;
|
||||
case STATUS_ISSUES_NOT_ENABLED:
|
||||
return RESULT_ISSUES_NOT_ENABLED;
|
||||
default:
|
||||
e.printStackTrace();
|
||||
return RESULT_UNKNOWN;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return RESULT_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(@Result String result) {
|
||||
super.onPostExecute(result);
|
||||
|
||||
Context context = getContext();
|
||||
if (context == null) return;
|
||||
|
||||
switch (result) {
|
||||
case RESULT_OK:
|
||||
mReportFailed = false;
|
||||
tryToFinishActivity();
|
||||
break;
|
||||
case RESULT_BAD_CREDENTIALS:
|
||||
new MaterialDialog.Builder(context)
|
||||
.title(R.string.air_dialog_title_failed)
|
||||
.content(R.string.air_dialog_description_failed_wrong_credentials)
|
||||
.positiveText(R.string.air_dialog_action_failed)
|
||||
.show();
|
||||
break;
|
||||
case RESULT_INVALID_TOKEN:
|
||||
new MaterialDialog.Builder(context)
|
||||
.title(R.string.air_dialog_title_failed)
|
||||
.content(R.string.air_dialog_description_failed_invalid_token)
|
||||
.positiveText(R.string.air_dialog_action_failed)
|
||||
.show();
|
||||
break;
|
||||
case RESULT_ISSUES_NOT_ENABLED:
|
||||
new MaterialDialog.Builder(context)
|
||||
.title(R.string.air_dialog_title_failed)
|
||||
.content(R.string.air_dialog_description_failed_issues_not_available)
|
||||
.positiveText(R.string.air_dialog_action_failed)
|
||||
.show();
|
||||
break;
|
||||
default:
|
||||
new MaterialDialog.Builder(context)
|
||||
.title(R.string.air_dialog_title_failed)
|
||||
.content(R.string.air_dialog_description_failed_unknown)
|
||||
.positiveText(R.string.air_dialog_action_failed)
|
||||
.onPositive(new MaterialDialog.SingleButtonCallback() {
|
||||
@Override
|
||||
public void onClick(@NonNull MaterialDialog dialog,
|
||||
@NonNull DialogAction which) {
|
||||
tryToFinishActivity();
|
||||
}
|
||||
})
|
||||
.cancelListener(new DialogInterface.OnCancelListener() {
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
tryToFinishActivity();
|
||||
}
|
||||
})
|
||||
.show();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void tryToFinishActivity() {
|
||||
Context context = getContext();
|
||||
if (context instanceof Activity && !((Activity) context).isFinishing()) {
|
||||
((Activity) context).finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static abstract class DialogAsyncTask<Pa, Pr, Re> extends AsyncTask<Pa, Pr, Re> {
|
||||
private WeakReference<Context> contextWeakReference;
|
||||
private WeakReference<Dialog> dialogWeakReference;
|
||||
|
||||
private boolean supposedToBeDismissed;
|
||||
|
||||
private DialogAsyncTask(Context context) {
|
||||
contextWeakReference = new WeakReference<>(context);
|
||||
dialogWeakReference = new WeakReference<>(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
super.onPreExecute();
|
||||
Context context = getContext();
|
||||
if (!supposedToBeDismissed && context != null) {
|
||||
Dialog dialog = createDialog(context);
|
||||
dialogWeakReference = new WeakReference<>(dialog);
|
||||
dialog.show();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected final void onProgressUpdate(Pr... values) {
|
||||
super.onProgressUpdate(values);
|
||||
Dialog dialog = getDialog();
|
||||
if (dialog != null) {
|
||||
onProgressUpdate(dialog, values);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void onProgressUpdate(@NonNull Dialog dialog, Pr... values) {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
Context getContext() {
|
||||
return contextWeakReference.get();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
Dialog getDialog() {
|
||||
return dialogWeakReference.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCancelled(Re result) {
|
||||
super.onCancelled(result);
|
||||
tryToDismiss();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Re result) {
|
||||
super.onPostExecute(result);
|
||||
tryToDismiss();
|
||||
}
|
||||
|
||||
private void tryToDismiss() {
|
||||
supposedToBeDismissed = true;
|
||||
try {
|
||||
Dialog dialog = getDialog();
|
||||
if (dialog != null)
|
||||
dialog.dismiss();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract Dialog createDialog(@NonNull Context context);
|
||||
}
|
||||
}
|
||||
@@ -79,7 +79,7 @@ public class ErrorReportActivity extends BaseActivity {
|
||||
}
|
||||
|
||||
private void startIssueReportActivity() {
|
||||
Intent intent = new Intent(this, IssueReportActivity.class);
|
||||
Intent intent = new Intent(this, IssueReporterActivity.class);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||
intent.putExtras(getIntent());
|
||||
startActivity(intent);
|
||||
|
||||
@@ -1,145 +0,0 @@
|
||||
package com.stardust.scriptdroid.ui.error;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.util.Base64;
|
||||
import android.view.View;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.heinrichreimersoftware.androidissuereporter.IssueReporterActivity;
|
||||
import com.heinrichreimersoftware.androidissuereporter.model.github.GithubTarget;
|
||||
import com.stardust.scriptdroid.R;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/2/13.
|
||||
*/
|
||||
|
||||
public class IssueReportActivity extends IssueReporterActivity {
|
||||
|
||||
private boolean mCrash = false;
|
||||
private Method mReportIssue, mValidateInput;
|
||||
private boolean mReportFailed = false;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
handleIntent();
|
||||
setUpToobar();
|
||||
hookSendClick();
|
||||
}
|
||||
|
||||
private void hookSendClick() {
|
||||
FloatingActionButton send = (FloatingActionButton) this.findViewById(com.heinrichreimersoftware.androidissuereporter.R.id.air_buttonSend);
|
||||
send.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
try {
|
||||
reportIssue();
|
||||
} catch (Exception e) {
|
||||
mReportFailed = true;
|
||||
e.printStackTrace();
|
||||
finish();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setUpToobar() {
|
||||
getSupportActionBar().setTitle(R.string.text_issue_report);
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
Toolbar toolbar = (Toolbar) findViewById(R.id.air_toolbar);
|
||||
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
finish();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void handleIntent() {
|
||||
final String errorDetail = getIntent().getStringExtra("error");
|
||||
if (errorDetail != null) {
|
||||
((EditText) findViewById(R.id.air_inputDescription)).setText(errorDetail);
|
||||
String title = getFirstLine(errorDetail);
|
||||
((EditText) findViewById(R.id.air_inputTitle)).setText(title);
|
||||
mCrash = true;
|
||||
}
|
||||
}
|
||||
|
||||
private String getFirstLine(String str) {
|
||||
int i = str.indexOf('\n');
|
||||
if(i < 0)
|
||||
return str;
|
||||
return str.substring(0, i);
|
||||
}
|
||||
|
||||
private boolean validateInput() {
|
||||
if (mValidateInput == null) {
|
||||
try {
|
||||
mValidateInput = IssueReporterActivity.class.getDeclaredMethod("validateInput");
|
||||
mValidateInput.setAccessible(true);
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
try {
|
||||
return mValidateInput != null && (Boolean) mValidateInput.invoke(this);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void reportIssue() {
|
||||
if (mReportIssue == null) {
|
||||
try {
|
||||
mReportIssue = IssueReporterActivity.class.getDeclaredMethod("reportIssue");
|
||||
mReportIssue.setAccessible(true);
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
try {
|
||||
mReportIssue.invoke(this);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish() {
|
||||
if (mCrash) {
|
||||
if (!mReportFailed) {
|
||||
Toast.makeText(IssueReportActivity.this, R.string.text_report_succeed, Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
Toast.makeText(IssueReportActivity.this, R.string.text_report_fail, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
finishAffinity();
|
||||
|
||||
} else {
|
||||
super.finish();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GithubTarget getTarget() {
|
||||
return new GithubTarget("hyb1996", "NoRootScriptDroid");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected String getGuestToken() {
|
||||
//绕过github安全检查
|
||||
return decode("MzA5MWJhNWI0NDM2NWYzOGRmNDA4ZWRhM2Y5MTUxN2ZlNDVlZDBhZQ==");
|
||||
}
|
||||
|
||||
public static String decode(String str) {
|
||||
return new String(Base64.decode(str.getBytes(), Base64.DEFAULT));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.stardust.scriptdroid.ui.error;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.util.Base64;
|
||||
|
||||
import com.heinrichreimersoftware.androidissuereporter.model.github.GithubTarget;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/2/13.
|
||||
*/
|
||||
|
||||
public class IssueReporterActivity extends AbstractIssueReporterActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
//绕过GitHub安全检查
|
||||
String token = decode("MzA5MWJhNWI0NDM2NWYzOGRmNDA4ZWRhM2Y5MTUxN2ZlNDVlZDBhZQ==");
|
||||
setGuestToken(token);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GithubTarget getTarget() {
|
||||
return new GithubTarget("hyb1996", "NoRootScriptDroid");
|
||||
}
|
||||
|
||||
|
||||
public static String decode(String str) {
|
||||
return new String(Base64.decode(str.getBytes(), Base64.DEFAULT));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -7,10 +7,7 @@ import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.design.widget.TabLayout;
|
||||
import android.support.v4.view.ViewPager;
|
||||
@@ -25,22 +22,23 @@ import android.widget.Toast;
|
||||
|
||||
import com.afollestad.materialdialogs.DialogAction;
|
||||
import com.afollestad.materialdialogs.MaterialDialog;
|
||||
import com.afollestad.materialdialogs.folderselector.FileChooserDialog;
|
||||
import com.stardust.app.FragmentPagerAdapterBuilder;
|
||||
import com.stardust.app.NotAskAgainDialog;
|
||||
import com.stardust.app.OnActivityResultDelegate;
|
||||
import com.stardust.scriptdroid.Pref;
|
||||
import com.stardust.scriptdroid.scripts.ScriptFile;
|
||||
import com.stardust.scriptdroid.scripts.StorageScriptProvider;
|
||||
import com.stardust.scriptdroid.service.AccessibilityWatchDogService;
|
||||
import com.stardust.scriptdroid.tool.AccessibilityServiceTool;
|
||||
import com.stardust.scriptdroid.tool.ImageSelector;
|
||||
import com.stardust.scriptdroid.tool.DrawableSaver;
|
||||
import com.stardust.scriptdroid.ui.BaseActivity;
|
||||
import com.stardust.scriptdroid.ui.main.my_script_list.MyScriptListFragment;
|
||||
import com.stardust.scriptdroid.ui.main.script_list.MyScriptListFragment;
|
||||
import com.stardust.scriptdroid.ui.main.sample_list.SampleScriptListFragment;
|
||||
import com.stardust.scriptdroid.ui.main.script_list.ScriptFileChooserDialogBuilder;
|
||||
import com.stardust.scriptdroid.ui.main.task.TaskManagerFragment;
|
||||
import com.stardust.scriptdroid.ui.settings.SettingsActivity;
|
||||
import com.stardust.theme.dialog.ThemeColorMaterialDialogBuilder;
|
||||
import com.stardust.util.BackPressedHandler;
|
||||
import com.stardust.util.MessageEvent;
|
||||
import com.stardust.view.ViewBinding;
|
||||
import com.stardust.widget.SlidingUpPanel;
|
||||
import com.stardust.scriptdroid.BuildConfig;
|
||||
@@ -48,10 +46,13 @@ import com.stardust.scriptdroid.R;
|
||||
import com.stardust.view.ViewBinder;
|
||||
import com.stardust.view.accessibility.AccessibilityServiceUtils;
|
||||
|
||||
import java.io.File;
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
|
||||
|
||||
public class MainActivity extends BaseActivity implements FileChooserDialog.FileCallback {
|
||||
public class MainActivity extends BaseActivity {
|
||||
|
||||
public static final String MESSAGE_CLEAR_BACKGROUND_SETTINGS = "MESSAGE_CLEAR_BACKGROUND_SETTINGS";
|
||||
|
||||
private static final String EXTRA_ACTION = "EXTRA_ACTION";
|
||||
|
||||
@@ -66,6 +67,7 @@ public class MainActivity extends BaseActivity implements FileChooserDialog.File
|
||||
private FragmentPagerAdapterBuilder.StoredFragmentPagerAdapter mPagerAdapter;
|
||||
|
||||
private OnActivityResultDelegate.Intermediary mActivityResultIntermediary = new OnActivityResultDelegate.Intermediary();
|
||||
private DrawableSaver mDrawerHeaderBackgroundSaver, mAppbarBackgroundSaver;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
@@ -74,6 +76,7 @@ public class MainActivity extends BaseActivity implements FileChooserDialog.File
|
||||
checkPermissions();
|
||||
registerBackPressHandlers();
|
||||
handleIntent(getIntent());
|
||||
EventBus.getDefault().register(this);
|
||||
}
|
||||
|
||||
private void registerBackPressHandlers() {
|
||||
@@ -131,21 +134,7 @@ public class MainActivity extends BaseActivity implements FileChooserDialog.File
|
||||
private void setUpDrawerHeader() {
|
||||
TextView version = $(R.id.version);
|
||||
version.setText("Version " + BuildConfig.VERSION_NAME);
|
||||
String path = Pref.getDrawerHeaderImagePath();
|
||||
if (path != null) {
|
||||
setDrawerHeaderImage(path);
|
||||
}
|
||||
path = Pref.getAppBarImagePath();
|
||||
if (path != null) {
|
||||
setAppBarImage(path);
|
||||
}
|
||||
}
|
||||
|
||||
private void setDrawerHeaderImage(String path) {
|
||||
Drawable d = BitmapDrawable.createFromPath(path);
|
||||
if (d != null) {
|
||||
((ImageView) $(R.id.drawer_header_img)).setImageDrawable(d);
|
||||
}
|
||||
mDrawerHeaderBackgroundSaver = new DrawableSaver.ImageSaver(this, "drawer_header_background", (ImageView) $(R.id.drawer_header_img));
|
||||
}
|
||||
|
||||
private void setUpToolbar() {
|
||||
@@ -156,6 +145,7 @@ public class MainActivity extends BaseActivity implements FileChooserDialog.File
|
||||
R.string.text_drawer_close);
|
||||
drawerToggle.syncState();
|
||||
mDrawerLayout.addDrawerListener(drawerToggle);
|
||||
mAppbarBackgroundSaver = new DrawableSaver.ImageSaver(this, "appbar_background", (ImageView) $(R.id.app_bar_bg));
|
||||
}
|
||||
|
||||
private void setUpTabViewPager() {
|
||||
@@ -167,6 +157,7 @@ public class MainActivity extends BaseActivity implements FileChooserDialog.File
|
||||
.add(new TaskManagerFragment(), R.string.text_task_manage)
|
||||
.build();
|
||||
viewPager.setAdapter(mPagerAdapter);
|
||||
viewPager.setOffscreenPageLimit(mPagerAdapter.getCount());
|
||||
tabLayout.setupWithViewPager(viewPager);
|
||||
}
|
||||
|
||||
@@ -187,9 +178,30 @@ public class MainActivity extends BaseActivity implements FileChooserDialog.File
|
||||
|
||||
@ViewBinding.Click(R.id.import_from_file)
|
||||
private void showFileChooser() {
|
||||
new FileChooserDialog.Builder(this)
|
||||
.initialPath(Environment.getExternalStorageDirectory().getPath())
|
||||
.extensionsFilter(".js", ".txt")
|
||||
new ScriptFileChooserDialogBuilder(this)
|
||||
.scriptProvider(StorageScriptProvider.getExternalStorageProvider())
|
||||
.fileCallback(new ScriptFileChooserDialogBuilder.FileCallback() {
|
||||
@Override
|
||||
public void onFileSelection(MaterialDialog dialog, ScriptFile file) {
|
||||
dialog.dismiss();
|
||||
StorageScriptProvider.getExternalStorageProvider().clearCacheExceptInitialDirectory();
|
||||
getMyScriptListFragment().importFile(file.getPath());
|
||||
}
|
||||
})
|
||||
.title(R.string.text_please_choose_file_to_import)
|
||||
.autoDismiss(false)
|
||||
.positiveText(R.string.cancel)
|
||||
.neutralText(R.string.text_refresh)
|
||||
.onAny(new MaterialDialog.SingleButtonCallback() {
|
||||
@Override
|
||||
public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
|
||||
if (which == DialogAction.POSITIVE) {
|
||||
dialog.dismiss();
|
||||
} else {
|
||||
StorageScriptProvider.getExternalStorageProvider().refreshAll();
|
||||
}
|
||||
}
|
||||
})
|
||||
.show();
|
||||
}
|
||||
|
||||
@@ -205,19 +217,7 @@ public class MainActivity extends BaseActivity implements FileChooserDialog.File
|
||||
|
||||
@ViewBinding.Click(R.id.drawer_header_img)
|
||||
public void selectHeaderImage() {
|
||||
new ImageSelector(this, mActivityResultIntermediary, new ImageSelector.ImageSelectorCallback() {
|
||||
@Override
|
||||
public void onImageSelected(ImageSelector selector, String path) {
|
||||
setDrawerHeaderImage(path);
|
||||
Pref.setDrawerHeaderImagePath(path);
|
||||
mActivityResultIntermediary.removeDelegate(selector);
|
||||
}
|
||||
}).select();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFileSelection(@NonNull FileChooserDialog dialog, @NonNull File file) {
|
||||
getMyScriptListFragment().importFile(file.getPath());
|
||||
mDrawerHeaderBackgroundSaver.select(this, mActivityResultIntermediary);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -275,7 +275,7 @@ public class MainActivity extends BaseActivity implements FileChooserDialog.File
|
||||
.putExtra(ARGUMENT_PATH, path));
|
||||
}
|
||||
|
||||
private MyScriptListFragment getMyScriptListFragment() {
|
||||
public MyScriptListFragment getMyScriptListFragment() {
|
||||
return ((MyScriptListFragment) mPagerAdapter.getStoredFragment(0));
|
||||
}
|
||||
|
||||
@@ -299,21 +299,20 @@ public class MainActivity extends BaseActivity implements FileChooserDialog.File
|
||||
|
||||
@ViewBinding.Click(R.id.toolbar)
|
||||
public void OnToolbarClick() {
|
||||
new ImageSelector(this, mActivityResultIntermediary, new ImageSelector.ImageSelectorCallback() {
|
||||
@Override
|
||||
public void onImageSelected(ImageSelector selector, String path) {
|
||||
Pref.setAppBarImagePath(path);
|
||||
setAppBarImage(path);
|
||||
mActivityResultIntermediary.removeDelegate(selector);
|
||||
}
|
||||
}).select();
|
||||
mAppbarBackgroundSaver.select(this, mActivityResultIntermediary);
|
||||
}
|
||||
|
||||
private void setAppBarImage(String path) {
|
||||
Drawable d = BitmapDrawable.createFromPath(path);
|
||||
if (d != null) {
|
||||
((ImageView) $(R.id.app_bar_bg)).setImageDrawable(d);
|
||||
@Subscribe
|
||||
public void onMessageEvent(MessageEvent event) {
|
||||
if (event.message.equals(MESSAGE_CLEAR_BACKGROUND_SETTINGS)) {
|
||||
mAppbarBackgroundSaver.reset();
|
||||
mDrawerHeaderBackgroundSaver.reset();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
EventBus.getDefault().unregister(this);
|
||||
}
|
||||
}
|
||||
@@ -9,18 +9,13 @@ import android.view.ViewGroup;
|
||||
|
||||
import com.afollestad.materialdialogs.MaterialDialog;
|
||||
import com.stardust.app.Fragment;
|
||||
import com.stardust.scriptdroid.scripts.ScriptFile;
|
||||
import com.stardust.scriptdroid.scripts.ScriptFileList;
|
||||
import com.stardust.pio.PFile;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.scripts.StorageScriptProvider;
|
||||
import com.stardust.scriptdroid.scripts.sample.Sample;
|
||||
import com.stardust.scriptdroid.scripts.sample.SampleFileManager;
|
||||
import com.stardust.scriptdroid.ui.edit.EditActivity;
|
||||
import com.stardust.scriptdroid.ui.main.my_script_list.MyScriptListFragment;
|
||||
import com.stardust.util.MessageEvent;
|
||||
import com.stardust.scriptdroid.ui.main.MainActivity;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/13.
|
||||
@@ -70,13 +65,12 @@ public class SampleScriptListFragment extends Fragment {
|
||||
}
|
||||
|
||||
private void copySampleToMyScripts(Sample sample) {
|
||||
String path = StorageScriptProvider.DEFAULT_DIRECTORY_PATH + sample.name + ".js";
|
||||
if (!ScriptFileList.getImpl().containsPath(path) && PFile.copyAsset(getActivity(), sample.path, path)) {
|
||||
ScriptFileList.getImpl().add(new ScriptFile(path));
|
||||
EventBus.getDefault().post(new MessageEvent(MyScriptListFragment.MESSAGE_SCRIPT_FILE_ADDED));
|
||||
Snackbar.make(mSampleScriptListRecyclerView, R.string.text_import_succeed, Snackbar.LENGTH_SHORT).show();
|
||||
} else {
|
||||
Snackbar.make(mSampleScriptListRecyclerView, R.string.text_file_exists, Snackbar.LENGTH_SHORT).show();
|
||||
try {
|
||||
((MainActivity) getActivity()).getMyScriptListFragment().
|
||||
importFile(sample.name, getActivity().getAssets().open(sample.path));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
Snackbar.make(mSampleScriptListRecyclerView, R.string.text_import_fail, Snackbar.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.stardust.scriptdroid.ui.main.my_script_list;
|
||||
package com.stardust.scriptdroid.ui.main.script_list;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
@@ -24,6 +24,9 @@ import com.stardust.view.ViewBinding;
|
||||
import com.stardust.widget.SimpleAdapterDataObserver;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/13.
|
||||
@@ -34,8 +37,8 @@ public class MyScriptListFragment extends Fragment {
|
||||
public static final String MESSAGE_SCRIPT_FILE_ADDED = "MESSAGE_SCRIPT_FILE_ADDED";
|
||||
|
||||
private ScriptAndFolderListRecyclerView mScriptListRecyclerView;
|
||||
private ScriptListWithProgressBarView mScriptListWithProgressBarView;
|
||||
private View mNoScriptHint;
|
||||
private View mProgressBar;
|
||||
private MaterialDialog mScriptFileOperationDialog;
|
||||
private MaterialDialog mDirectoryOperationDialog;
|
||||
private ScriptFile mSelectedScriptFile;
|
||||
@@ -57,14 +60,15 @@ public class MyScriptListFragment extends Fragment {
|
||||
@Override
|
||||
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
mScriptListRecyclerView = $(R.id.script_list);
|
||||
mScriptListWithProgressBarView = $(R.id.script_list);
|
||||
mScriptListRecyclerView = mScriptListWithProgressBarView.getScriptAndFolderListRecyclerView();
|
||||
mNoScriptHint = $(R.id.hint_no_script);
|
||||
mProgressBar = $(R.id.progressBar);
|
||||
initScriptListRecyclerView();
|
||||
initDialogs();
|
||||
}
|
||||
|
||||
private void initScriptListRecyclerView() {
|
||||
mScriptListWithProgressBarView.setStorageScriptProvider(StorageScriptProvider.getDefault());
|
||||
mScriptListRecyclerView.getAdapter().registerAdapterDataObserver(new SimpleAdapterDataObserver() {
|
||||
@Override
|
||||
public void onSomethingChanged() {
|
||||
@@ -141,14 +145,22 @@ public class MyScriptListFragment extends Fragment {
|
||||
}
|
||||
|
||||
public void importFile(final String pathFrom) {
|
||||
showFileNameInputDialog(PFile.getNameWithoutExtension(pathFrom), new MaterialDialog.InputCallback() {
|
||||
try {
|
||||
importFile(PFile.getNameWithoutExtension(pathFrom), new FileInputStream(pathFrom));
|
||||
} catch (FileNotFoundException e) {
|
||||
showMessage(R.string.file_not_exists);
|
||||
}
|
||||
}
|
||||
|
||||
public void importFile(String prefix, final InputStream inputStream) {
|
||||
showFileNameInputDialog(PFile.getNameWithoutExtension(prefix), new MaterialDialog.InputCallback() {
|
||||
@Override
|
||||
public void onInput(@NonNull MaterialDialog dialog, CharSequence input) {
|
||||
final String pathTo = getCurrentDirectoryPath() + input + ".js";
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (PFile.copy(pathFrom, pathTo)) {
|
||||
if (PFile.copyStream(inputStream, pathTo)) {
|
||||
showMessage(R.string.text_import_succeed);
|
||||
} else {
|
||||
showMessage(R.string.text_import_fail);
|
||||
@@ -156,7 +168,6 @@ public class MyScriptListFragment extends Fragment {
|
||||
notifyScriptFileChanged();
|
||||
}
|
||||
}).start();
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -237,10 +248,10 @@ public class MyScriptListFragment extends Fragment {
|
||||
|
||||
private void onScriptFileOperated() {
|
||||
mSelectedScriptFile = null;
|
||||
mProgressBar.post(new Runnable() {
|
||||
getView().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mProgressBar.setVisibility(View.GONE);
|
||||
mScriptListWithProgressBarView.hideProgressBar();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -276,7 +287,7 @@ public class MyScriptListFragment extends Fragment {
|
||||
}
|
||||
|
||||
private void doDeletingScriptFile() {
|
||||
mProgressBar.setVisibility(View.VISIBLE);
|
||||
mScriptListWithProgressBarView.showProgressBar();
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.stardust.scriptdroid.ui.main.my_script_list;
|
||||
package com.stardust.scriptdroid.ui.main.script_list;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
@@ -17,7 +17,6 @@ import android.widget.TextView;
|
||||
import com.stardust.autojs.script.FileScriptSource;
|
||||
import com.stardust.scriptdroid.autojs.AutoJs;
|
||||
import com.stardust.scriptdroid.scripts.ScriptFile;
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.scripts.StorageScriptProvider;
|
||||
import com.stardust.scriptdroid.ui.main.operation.ScriptFileOperation;
|
||||
@@ -40,6 +39,13 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView {
|
||||
void onLongClick(ScriptFile file);
|
||||
}
|
||||
|
||||
public interface FileProcessListener {
|
||||
|
||||
void onFilesListing();
|
||||
|
||||
void onFileListed();
|
||||
}
|
||||
|
||||
private OnScriptFileClickListener mOnItemClickListener;
|
||||
private OnScriptFileLongClickListener mOnItemLongClickListener;
|
||||
private final OnClickListener mOnItemClickListenerProxy = new OnClickListener() {
|
||||
@@ -86,13 +92,14 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView {
|
||||
}
|
||||
};
|
||||
|
||||
private ScriptFile[] mScriptFileList;
|
||||
|
||||
private ScriptFile[] mScriptFileList = new ScriptFile[0];
|
||||
private ScriptFile mCurrentFolder;
|
||||
private ScriptFile mRootFolder;
|
||||
private Adapter mAdapter;
|
||||
private boolean mCanGoBack;
|
||||
private StorageScriptProvider mStorageScriptProvider = StorageScriptProvider.getDefault();
|
||||
private boolean mCanGoBack = false;
|
||||
private StorageScriptProvider mStorageScriptProvider;
|
||||
private FileProcessListener mFileProcessListener;
|
||||
private boolean mScriptFileOperationEnabled = true;
|
||||
|
||||
public ScriptAndFolderListRecyclerView(Context context) {
|
||||
super(context);
|
||||
@@ -109,11 +116,25 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView {
|
||||
init();
|
||||
}
|
||||
|
||||
private void setCurrentFolder(ScriptFile folder, boolean canGoBack) {
|
||||
private void setCurrentFolder(final ScriptFile folder, boolean canGoBack) {
|
||||
mCurrentFolder = folder;
|
||||
mScriptFileList = mStorageScriptProvider.getDirectoryScriptFiles(folder);
|
||||
mCanGoBack = canGoBack;
|
||||
mAdapter.notifyDataSetChanged();
|
||||
if (mFileProcessListener != null) {
|
||||
mFileProcessListener.onFilesListing();
|
||||
}
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mScriptFileList = mStorageScriptProvider.getDirectoryScriptFiles(folder);
|
||||
post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mFileProcessListener.onFileListed();
|
||||
mAdapter.notifyDataSetChanged();
|
||||
}
|
||||
});
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
private void setRootFolder(ScriptFile folder) {
|
||||
@@ -121,8 +142,16 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView {
|
||||
setCurrentFolder(mRootFolder, false);
|
||||
}
|
||||
|
||||
public void setFileProcessListener(FileProcessListener fileProcessListener) {
|
||||
mFileProcessListener = fileProcessListener;
|
||||
}
|
||||
|
||||
public void setStorageScriptProvider(StorageScriptProvider storageScriptProvider) {
|
||||
if (mStorageScriptProvider != null)
|
||||
mStorageScriptProvider.unregisterDirectoryChangeListener(this);
|
||||
mStorageScriptProvider = storageScriptProvider;
|
||||
mStorageScriptProvider.registerDirectoryChangeListener(this);
|
||||
setRootFolder(mStorageScriptProvider.getInitialDirectory());
|
||||
}
|
||||
|
||||
public void setOnItemClickListener(OnScriptFileClickListener onItemClickListener) {
|
||||
@@ -137,6 +166,10 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView {
|
||||
return mCurrentFolder;
|
||||
}
|
||||
|
||||
public void setScriptFileOperationEnabled(boolean scriptFileOperationEnabled) {
|
||||
mScriptFileOperationEnabled = scriptFileOperationEnabled;
|
||||
}
|
||||
|
||||
private void goBack() {
|
||||
ScriptFile parent = mCurrentFolder.getParentFile();
|
||||
setCurrentFolder(parent, !parent.equals(mRootFolder));
|
||||
@@ -147,7 +180,6 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView {
|
||||
addItemDecoration(new DividerItemDecoration(getContext(), VERTICAL));
|
||||
mAdapter = new Adapter();
|
||||
setAdapter(mAdapter);
|
||||
setRootFolder(mStorageScriptProvider.getInitialDirectory());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -171,7 +203,8 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView {
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
mStorageScriptProvider.registerDirectoryChangeListener(this);
|
||||
if (mStorageScriptProvider != null)
|
||||
mStorageScriptProvider.registerDirectoryChangeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -268,8 +301,13 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView {
|
||||
|
||||
FileViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
itemView.findViewById(R.id.edit).setOnClickListener(mOnEditClickListener);
|
||||
itemView.findViewById(R.id.run).setOnClickListener(mOnRunClickListener);
|
||||
if (mScriptFileOperationEnabled) {
|
||||
itemView.findViewById(R.id.edit).setOnClickListener(mOnEditClickListener);
|
||||
itemView.findViewById(R.id.run).setOnClickListener(mOnRunClickListener);
|
||||
} else {
|
||||
itemView.findViewById(R.id.edit).setVisibility(GONE);
|
||||
itemView.findViewById(R.id.run).setVisibility(GONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.stardust.scriptdroid.ui.main.script_list;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import com.afollestad.materialdialogs.MaterialDialog;
|
||||
import com.stardust.scriptdroid.scripts.ScriptFile;
|
||||
import com.stardust.scriptdroid.scripts.StorageScriptProvider;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/4/3.
|
||||
*/
|
||||
|
||||
public class ScriptFileChooserDialogBuilder extends MaterialDialog.Builder {
|
||||
|
||||
public interface FileCallback {
|
||||
void onFileSelection(MaterialDialog dialog, ScriptFile file);
|
||||
}
|
||||
|
||||
private ScriptListWithProgressBarView mScriptListWithProgressBarView;
|
||||
private StorageScriptProvider mStorageScriptProvider;
|
||||
private FileCallback mFileCallback;
|
||||
|
||||
public ScriptFileChooserDialogBuilder(@NonNull Context context) {
|
||||
super(context);
|
||||
mScriptListWithProgressBarView = new ScriptListWithProgressBarView(context);
|
||||
mScriptListWithProgressBarView.setMinimumHeight(800);
|
||||
mScriptListWithProgressBarView.setScriptFileOperationEnabled(false);
|
||||
}
|
||||
|
||||
public ScriptFileChooserDialogBuilder fileCallback(final FileCallback fileCallback) {
|
||||
mFileCallback = fileCallback;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ScriptFileChooserDialogBuilder initialPath(String initialPath) {
|
||||
mStorageScriptProvider = new StorageScriptProvider(initialPath, 5);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ScriptFileChooserDialogBuilder scriptProvider(StorageScriptProvider storageScriptProvider) {
|
||||
mStorageScriptProvider = storageScriptProvider;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MaterialDialog build() {
|
||||
if (mStorageScriptProvider != null) {
|
||||
mScriptListWithProgressBarView.setStorageScriptProvider(mStorageScriptProvider);
|
||||
}
|
||||
customView(mScriptListWithProgressBarView, false);
|
||||
final MaterialDialog dialog = super.build();
|
||||
if (mFileCallback != null) {
|
||||
mScriptListWithProgressBarView.setOnItemClickListener(new ScriptAndFolderListRecyclerView.OnScriptFileClickListener() {
|
||||
@Override
|
||||
public void onClick(ScriptFile file) {
|
||||
mFileCallback.onFileSelection(dialog, file);
|
||||
}
|
||||
});
|
||||
}
|
||||
return dialog;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.stardust.scriptdroid.ui.main.my_script_list;
|
||||
package com.stardust.scriptdroid.ui.main.script_list;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.Nullable;
|
||||
@@ -0,0 +1,92 @@
|
||||
package com.stardust.scriptdroid.ui.main.script_list;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.support.annotation.AttrRes;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.RequiresApi;
|
||||
import android.support.annotation.StyleRes;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.scripts.StorageScriptProvider;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/4/3.
|
||||
*/
|
||||
|
||||
public class ScriptListWithProgressBarView extends FrameLayout {
|
||||
|
||||
private View mProgressBar;
|
||||
private ScriptAndFolderListRecyclerView mScriptAndFolderListRecyclerView;
|
||||
|
||||
public ScriptListWithProgressBarView(@NonNull Context context) {
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
public ScriptListWithProgressBarView(@NonNull Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
public ScriptListWithProgressBarView(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init();
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
public ScriptListWithProgressBarView(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr, @StyleRes int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
inflate(getContext(), R.layout.script_and_folder_list_view, this);
|
||||
mProgressBar = findViewById(R.id.progressBar);
|
||||
mScriptAndFolderListRecyclerView = (ScriptAndFolderListRecyclerView) findViewById(R.id.script_list_recycler_view);
|
||||
mScriptAndFolderListRecyclerView.setFileProcessListener(new ScriptAndFolderListRecyclerView.FileProcessListener() {
|
||||
@Override
|
||||
public void onFilesListing() {
|
||||
showProgressBar();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFileListed() {
|
||||
hideProgressBar();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public ScriptAndFolderListRecyclerView getScriptAndFolderListRecyclerView() {
|
||||
return mScriptAndFolderListRecyclerView;
|
||||
}
|
||||
|
||||
|
||||
public void setStorageScriptProvider(StorageScriptProvider storageScriptProvider) {
|
||||
mScriptAndFolderListRecyclerView.setStorageScriptProvider(storageScriptProvider);
|
||||
}
|
||||
|
||||
public void setOnItemClickListener(ScriptAndFolderListRecyclerView.OnScriptFileClickListener onItemClickListener) {
|
||||
mScriptAndFolderListRecyclerView.setOnItemClickListener(onItemClickListener);
|
||||
}
|
||||
|
||||
public void setScriptFileOperationEnabled(boolean enabled) {
|
||||
mScriptAndFolderListRecyclerView.setScriptFileOperationEnabled(enabled);
|
||||
}
|
||||
|
||||
|
||||
public void showProgressBar() {
|
||||
mProgressBar.setVisibility(VISIBLE);
|
||||
}
|
||||
|
||||
public void hideProgressBar() {
|
||||
mProgressBar.setVisibility(GONE);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -12,12 +12,16 @@ import android.widget.Toast;
|
||||
|
||||
import com.stardust.scriptdroid.Pref;
|
||||
import com.stardust.scriptdroid.ui.BaseActivity;
|
||||
import com.stardust.scriptdroid.ui.error.IssueReportActivity;
|
||||
import com.stardust.scriptdroid.ui.error.IssueReporterActivity;
|
||||
import com.stardust.scriptdroid.ui.main.MainActivity;
|
||||
import com.stardust.util.IntentUtil;
|
||||
import com.stardust.util.MapEntries;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.theme.app.ColorSelectActivity;
|
||||
import com.stardust.theme.util.ListBuilder;
|
||||
import com.stardust.util.MessageEvent;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -108,15 +112,13 @@ public class SettingsActivity extends BaseActivity {
|
||||
.entry(getString(R.string.text_reset_background), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Pref.setAppBarImagePath(null);
|
||||
Pref.setDrawerHeaderImagePath(null);
|
||||
Toast.makeText(getActivity(), R.string.text_restart_app_to_apply, Toast.LENGTH_SHORT).show();
|
||||
EventBus.getDefault().post(new MessageEvent(MainActivity.MESSAGE_CLEAR_BACKGROUND_SETTINGS));
|
||||
}
|
||||
})
|
||||
.entry(getString(R.string.text_issue_report), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
startActivity(new Intent(getActivity(), IssueReportActivity.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
|
||||
startActivity(new Intent(getActivity(), IssueReporterActivity.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
|
||||
}
|
||||
})
|
||||
.entry(getString(R.string.text_join_qq_group), new Runnable() {
|
||||
|
||||
Reference in New Issue
Block a user