Merge branch 'dev' of https://github.com/hyb1996/NoRootScriptDroid into dev
# Conflicts: # .idea/caches/build_file_checksums.ser
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
package org.autojs.autojs;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
@@ -10,29 +12,26 @@ import android.widget.ImageView;
|
||||
import com.bumptech.glide.request.target.SimpleTarget;
|
||||
import com.bumptech.glide.request.transition.Transition;
|
||||
import com.flurry.android.FlurryAgent;
|
||||
import com.raizlabs.android.dbflow.config.DatabaseConfig;
|
||||
import com.raizlabs.android.dbflow.config.FlowConfig;
|
||||
import com.raizlabs.android.dbflow.config.FlowManager;
|
||||
import com.raizlabs.android.dbflow.runtime.DirectModelNotifier;
|
||||
import com.squareup.leakcanary.LeakCanary;
|
||||
import com.stardust.app.GlobalAppContext;
|
||||
import com.stardust.autojs.core.ui.inflater.ImageLoader;
|
||||
import com.stardust.autojs.core.ui.inflater.util.Drawables;
|
||||
|
||||
import org.autojs.autojs.autojs.AutoJs;
|
||||
import org.autojs.autojs.autojs.key.GlobalKeyObserver;
|
||||
import org.autojs.autojs.network.GlideApp;
|
||||
import org.autojs.autojs.storage.database.IntentTaskDatabase;
|
||||
import org.autojs.autojs.storage.database.TimedTaskDatabase;
|
||||
import org.autojs.autojs.timing.TimedTaskScheduler;
|
||||
import org.autojs.autojs.tool.CrashHandler;
|
||||
import org.autojs.autojs.ui.error.ErrorReportActivity;
|
||||
|
||||
import com.stardust.theme.ThemeColor;
|
||||
import com.stardust.theme.ThemeColorManager;
|
||||
import com.tencent.bugly.crashreport.CrashReport;
|
||||
|
||||
import org.autojs.autojs.autojs.AutoJs;
|
||||
import org.autojs.autojs.autojs.key.GlobalKeyObserver;
|
||||
import org.autojs.autojs.external.receiver.DynamicBroadcastReceivers;
|
||||
import org.autojs.autojs.network.GlideApp;
|
||||
import org.autojs.autojs.timing.IntentTask;
|
||||
import org.autojs.autojs.timing.TimedTaskManager;
|
||||
import org.autojs.autojs.timing.TimedTaskScheduler;
|
||||
import org.autojs.autojs.tool.CrashHandler;
|
||||
import org.autojs.autojs.ui.error.ErrorReportActivity;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/27.
|
||||
@@ -44,6 +43,7 @@ public class App extends MultiDexApplication {
|
||||
private static final String BUGLY_APP_ID = "19b3607b53";
|
||||
|
||||
private static WeakReference<App> instance;
|
||||
private DynamicBroadcastReceivers mDynamicBroadcastReceivers;
|
||||
|
||||
public static App getApp() {
|
||||
return instance.get();
|
||||
@@ -58,6 +58,10 @@ public class App extends MultiDexApplication {
|
||||
init();
|
||||
}
|
||||
|
||||
public DynamicBroadcastReceivers getDynamicBroadcastReceivers() {
|
||||
return mDynamicBroadcastReceivers;
|
||||
}
|
||||
|
||||
private void setUpStaticsTool() {
|
||||
if (BuildConfig.DEBUG)
|
||||
return;
|
||||
@@ -67,6 +71,11 @@ public class App extends MultiDexApplication {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void attachBaseContext(Context base) {
|
||||
super.attachBaseContext(base);
|
||||
}
|
||||
|
||||
private void setUpDebugEnvironment() {
|
||||
CrashHandler crashHandler = new CrashHandler(ErrorReportActivity.class);
|
||||
|
||||
@@ -77,17 +86,16 @@ public class App extends MultiDexApplication {
|
||||
|
||||
crashHandler.setBuglyHandler(Thread.getDefaultUncaughtExceptionHandler());
|
||||
Thread.setDefaultUncaughtExceptionHandler(crashHandler);
|
||||
if (LeakCanary.isInAnalyzerProcess(this)) {
|
||||
// This process is dedicated to LeakCanary for heap analysis.
|
||||
// You should not init your app in this process.
|
||||
return;
|
||||
}
|
||||
//LeakCanary.install(this);
|
||||
|
||||
}
|
||||
|
||||
private void init() {
|
||||
FlowManager.init(FlowConfig.builder(this)
|
||||
.addDatabaseConfig(DatabaseConfig.builder(TimedTaskDatabase.class)
|
||||
.modelNotifier(DirectModelNotifier.get())
|
||||
.build())
|
||||
.addDatabaseConfig(DatabaseConfig.builder(IntentTaskDatabase.class)
|
||||
.modelNotifier(DirectModelNotifier.get())
|
||||
.build())
|
||||
.build());
|
||||
ThemeColorManager.setDefaultThemeColor(new ThemeColor(getResources().getColor(R.color.colorPrimary), getResources().getColor(R.color.colorPrimaryDark), getResources().getColor(R.color.colorAccent)));
|
||||
ThemeColorManager.init(this);
|
||||
AutoJs.initInstance(this);
|
||||
@@ -96,6 +104,18 @@ public class App extends MultiDexApplication {
|
||||
}
|
||||
setupDrawableImageLoader();
|
||||
TimedTaskScheduler.checkTasksRepeatedlyIfNeeded(this);
|
||||
initDynamicBroadcastReceivers();
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
private void initDynamicBroadcastReceivers() {
|
||||
mDynamicBroadcastReceivers = new DynamicBroadcastReceivers(this);
|
||||
TimedTaskManager.getInstance().getAllIntentTasks()
|
||||
.filter(task -> task.getAction() != null)
|
||||
.map(IntentTask::getAction)
|
||||
.collectInto(new ArrayList<String>(), ArrayList::add)
|
||||
.subscribe(list -> mDynamicBroadcastReceivers.register(list),
|
||||
Throwable::printStackTrace);
|
||||
}
|
||||
|
||||
private void setupDrawableImageLoader() {
|
||||
|
||||
@@ -201,4 +201,8 @@ public class Pref {
|
||||
getString(R.string.default_value_script_dir_path));
|
||||
return new File(Environment.getExternalStorageDirectory(), dir).getPath();
|
||||
}
|
||||
|
||||
public static boolean isForegroundServiceEnabled() {
|
||||
return def().getBoolean(getString(R.string.key_foreground_servie), false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ public class AutoJsApkBuilder extends ApkBuilder {
|
||||
public static AppConfig fromProjectConfig(String projectDir, ProjectConfig projectConfig) {
|
||||
return new AppConfig()
|
||||
.setAppName(projectConfig.getName())
|
||||
.setPackageName(projectConfig.getPackageName())
|
||||
.ignoreDir(new File(projectDir, projectConfig.getBuildDir()))
|
||||
.setVersionCode(projectConfig.getVersionCode())
|
||||
.setVersionName(projectConfig.getVersionName())
|
||||
|
||||
88
app/src/main/java/org/autojs/autojs/external/foreground/ForegroundService.java
vendored
Normal file
88
app/src/main/java/org/autojs/autojs/external/foreground/ForegroundService.java
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
package org.autojs.autojs.external.foreground;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.IBinder;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.RequiresApi;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
|
||||
import com.stardust.app.GlobalAppContext;
|
||||
|
||||
import org.autojs.autojs.R;
|
||||
import org.autojs.autojs.ui.main.MainActivity_;
|
||||
|
||||
public class ForegroundService extends Service {
|
||||
|
||||
|
||||
private static final int NOTIFICATION_ID = 1;
|
||||
private static final String CHANEL_ID = ForegroundService.class.getName() + ".foreground";
|
||||
|
||||
public static void start(Context context) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
context.startForegroundService(new Intent(context, ForegroundService.class));
|
||||
} else {
|
||||
context.startService(new Intent(context, ForegroundService.class));
|
||||
}
|
||||
}
|
||||
|
||||
public static void stop(Context context){
|
||||
context.stopService(new Intent(context, ForegroundService.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
startForeground();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
private void startForeground() {
|
||||
startForeground(NOTIFICATION_ID, buildNotification());
|
||||
}
|
||||
|
||||
private Notification buildNotification() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
createNotificationChannel();
|
||||
}
|
||||
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, MainActivity_.intent(this).get(), 0);
|
||||
return new NotificationCompat.Builder(this, CHANEL_ID)
|
||||
.setContentTitle(getString(R.string.foreground_notification_title))
|
||||
.setContentText(getString(R.string.foreground_notification_text))
|
||||
.setSmallIcon(R.drawable.autojs_material)
|
||||
.setWhen(System.currentTimeMillis())
|
||||
.setContentIntent(contentIntent)
|
||||
.setChannelId(CHANEL_ID)
|
||||
.build();
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||
private void createNotificationChannel() {
|
||||
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
assert manager != null;
|
||||
CharSequence name = getString(R.string.foreground_notification_channel_name);
|
||||
String description = getString(R.string.foreground_notification_channel_name);
|
||||
NotificationChannel channel = new NotificationChannel(CHANEL_ID, name, NotificationManager.IMPORTANCE_DEFAULT);
|
||||
channel.setDescription(description);
|
||||
channel.enableLights(false);
|
||||
manager.createNotificationChannel(channel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
stopForeground(true);
|
||||
super.onDestroy();
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.autojs.autojs.external.boot;
|
||||
package org.autojs.autojs.external.receiver;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.BroadcastReceiver;
|
||||
@@ -7,6 +7,7 @@ import android.content.Intent;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.stardust.app.GlobalAppContext;
|
||||
import com.stardust.autojs.execution.ExecutionConfig;
|
||||
|
||||
import org.autojs.autojs.autojs.AutoJs;
|
||||
@@ -17,23 +18,25 @@ import org.autojs.autojs.timing.TimedTaskManager;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
public class BootCompleteReceiver extends BroadcastReceiver {
|
||||
public class BaseBroadcastReceiver extends BroadcastReceiver {
|
||||
|
||||
private static final String LOG_TAG = "BootCompleteReceiver";
|
||||
private static final String LOG_TAG = "BaseBroadcastReceiver";
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
|
||||
Log.i(LOG_TAG, "on boot complete");
|
||||
Log.d(LOG_TAG, "onReceive: intent = " + intent + ", this = " + this);
|
||||
try {
|
||||
TimedTaskManager.getInstance().getIntentTaskOfAction(intent.getAction())
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(intentTask -> runTask(context, intent, intentTask), Throwable::printStackTrace);
|
||||
} catch (Exception e) {
|
||||
GlobalAppContext.toast(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void runTask(Context context, Intent intent, IntentTask task) {
|
||||
static void runTask(Context context, Intent intent, IntentTask task) {
|
||||
Log.d(LOG_TAG, "runTask: action = " + intent.getAction() + ", script = " + task.getScriptPath());
|
||||
ScriptFile file = new ScriptFile(task.getScriptPath());
|
||||
ExecutionConfig config = new ExecutionConfig();
|
||||
config.setArgument("intent", intent.clone());
|
||||
@@ -45,4 +48,5 @@ public class BootCompleteReceiver extends BroadcastReceiver {
|
||||
Toast.makeText(context, e.getMessage(), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
78
app/src/main/java/org/autojs/autojs/external/receiver/DynamicBroadcastReceivers.java
vendored
Normal file
78
app/src/main/java/org/autojs/autojs/external/receiver/DynamicBroadcastReceivers.java
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
package org.autojs.autojs.external.receiver;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.Build;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static android.content.Intent.ACTION_BATTERY_CHANGED;
|
||||
import static android.content.Intent.ACTION_CONFIGURATION_CHANGED;
|
||||
import static android.content.Intent.ACTION_PACKAGES_SUSPENDED;
|
||||
import static android.content.Intent.ACTION_PACKAGES_UNSUSPENDED;
|
||||
import static android.content.Intent.ACTION_SCREEN_OFF;
|
||||
import static android.content.Intent.ACTION_SCREEN_ON;
|
||||
import static android.content.Intent.ACTION_TIME_TICK;
|
||||
|
||||
public class DynamicBroadcastReceivers {
|
||||
|
||||
private static final List<String> DEFAULT_ACTIONS = new ArrayList<>(Arrays.asList(
|
||||
ACTION_TIME_TICK,
|
||||
ACTION_SCREEN_OFF,
|
||||
ACTION_SCREEN_ON,
|
||||
ACTION_BATTERY_CHANGED,
|
||||
ACTION_CONFIGURATION_CHANGED
|
||||
));
|
||||
|
||||
static {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
DEFAULT_ACTIONS.addAll(Arrays.asList(
|
||||
ACTION_PACKAGES_SUSPENDED,
|
||||
ACTION_PACKAGES_UNSUSPENDED
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
private final Set<String> mActions = new LinkedHashSet<>();
|
||||
private final List<BroadcastReceiver> mReceivers = new ArrayList<>();
|
||||
private final Context mContext;
|
||||
|
||||
|
||||
public DynamicBroadcastReceivers(Context context) {
|
||||
mContext = context;
|
||||
register(DEFAULT_ACTIONS);
|
||||
}
|
||||
|
||||
public void register(String action) {
|
||||
register(Collections.singletonList(action));
|
||||
}
|
||||
|
||||
public void register(List<String> actions) {
|
||||
IntentFilter filter = new IntentFilter();
|
||||
for (String action : actions) {
|
||||
if (!StaticBroadcastReceiver.ACTIONS.contains(action)
|
||||
&& !mActions.contains(action)) {
|
||||
mActions.add(action);
|
||||
filter.addAction(action);
|
||||
}
|
||||
}
|
||||
if (filter.countActions() == 0) {
|
||||
return;
|
||||
}
|
||||
BaseBroadcastReceiver receiver = new BaseBroadcastReceiver();
|
||||
mContext.registerReceiver(receiver, filter);
|
||||
}
|
||||
|
||||
public void unregisterAll() {
|
||||
for (BroadcastReceiver receiver : mReceivers) {
|
||||
mContext.unregisterReceiver(receiver);
|
||||
}
|
||||
mReceivers.clear();
|
||||
}
|
||||
}
|
||||
40
app/src/main/java/org/autojs/autojs/external/receiver/StaticBroadcastReceiver.java
vendored
Normal file
40
app/src/main/java/org/autojs/autojs/external/receiver/StaticBroadcastReceiver.java
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
package org.autojs.autojs.external.receiver;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class StaticBroadcastReceiver extends BaseBroadcastReceiver {
|
||||
|
||||
static final List<String> ACTIONS = new ArrayList<>(Arrays.asList(
|
||||
"android.intent.action.BOOT_COMPLETED",
|
||||
"android.intent.action.QUICKBOOT_POWERON",
|
||||
"android.intent.action.TIME_SET",
|
||||
"android.intent.action.TIMEZONE_CHANGED",
|
||||
"android.intent.action.PACKAGE_ADDED",
|
||||
"android.intent.action.PACKAGE_CHANGED",
|
||||
"android.intent.action.PACKAGE_DATA_CLEARED",
|
||||
"android.intent.action.PACKAGE_REMOVED",
|
||||
"android.intent.action.PACKAGE_RESTARTED",
|
||||
"android.intent.action.UID_REMOVED",
|
||||
"android.intent.action.ACTION_POWER_CONNECTED",
|
||||
"android.intent.action.ACTION_POWER_DISCONNECTED",
|
||||
"android.intent.action.ACTION_SHUTDOWN",
|
||||
"android.intent.action.DATE_CHANGED",
|
||||
"android.intent.action.DREAMING_STARTED",
|
||||
"android.intent.action.DREAMING_STOPPED",
|
||||
"android.intent.action.HEADSET_PLUG",
|
||||
"android.intent.action.INPUT_METHOD_CHANGED",
|
||||
"android.intent.action.LOCALE_CHANGED",
|
||||
"android.intent.action.MEDIA_BUTTON",
|
||||
"android.intent.action.MEDIA_CHECKING",
|
||||
"android.intent.action.MEDIA_MOUNTED",
|
||||
"android.intent.action.PACKAGE_FIRST_LAUNCH",
|
||||
"android.intent.action.PROVIDER_CHANGED",
|
||||
"android.intent.action.WALLPAPER_CHANGED",
|
||||
"android.intent.action.USER_UNLOCKED",
|
||||
"android.intent.action.USER_PRESENT",
|
||||
"android.net.conn.CONNECTIVITY_CHANGE"
|
||||
));
|
||||
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import android.content.Intent;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.autojs.autojs.R;
|
||||
import org.autojs.autojs.timing.TaskReceiver;
|
||||
import org.autojs.autojs.tool.EmptyObservers;
|
||||
import org.autojs.autojs.ui.BaseActivity;
|
||||
import org.autojs.autojs.ui.edit.EditorView;
|
||||
@@ -29,7 +30,8 @@ import static org.autojs.autojs.ui.edit.EditorView.EXTRA_SAVE_ENABLED;
|
||||
@EActivity(R.layout.activity_tasker_script_edit)
|
||||
public class TaskerScriptEditActivity extends BaseActivity {
|
||||
|
||||
public static final int REQUEST_CODE = "Love you. Can we go back?".hashCode() >> 16;
|
||||
public static final int REQUEST_CODE = 10016;
|
||||
public static final String EXTRA_TASK_ID = TaskReceiver.EXTRA_TASK_ID;
|
||||
|
||||
public static void edit(Activity activity, String title, String summary, String content) {
|
||||
activity.startActivityForResult(new Intent(activity, TaskerScriptEditActivity_.class)
|
||||
@@ -63,4 +65,9 @@ public class TaskerScriptEditActivity extends BaseActivity {
|
||||
TaskerScriptEditActivity.super.finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
mEditorView.destroy();
|
||||
super.onDestroy();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,4 +161,7 @@ public class AutoCompletion {
|
||||
}
|
||||
|
||||
|
||||
public void shutdown(){
|
||||
mExecutorService.shutdownNow();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,10 @@ public class Explorer {
|
||||
this(explorerProvider, cacheSize, EventBus.getDefault());
|
||||
}
|
||||
|
||||
public ExplorerProvider getProvider() {
|
||||
return mExplorerProvider;
|
||||
}
|
||||
|
||||
public void notifyChildrenChanged(ExplorerPage page) {
|
||||
clearCache(page);
|
||||
mEventBus.post(new ExplorerChangeEvent(page, CHILDREN_CHANGE, null));
|
||||
|
||||
@@ -4,16 +4,16 @@ import com.stardust.pio.PFile;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class ExplorerSamleItem extends ExplorerFileItem {
|
||||
public ExplorerSamleItem(PFile file, ExplorerPage parent) {
|
||||
public class ExplorerSampleItem extends ExplorerFileItem {
|
||||
public ExplorerSampleItem(PFile file, ExplorerPage parent) {
|
||||
super(file, parent);
|
||||
}
|
||||
|
||||
public ExplorerSamleItem(String path, ExplorerPage parent) {
|
||||
public ExplorerSampleItem(String path, ExplorerPage parent) {
|
||||
super(path, parent);
|
||||
}
|
||||
|
||||
public ExplorerSamleItem(File file, ExplorerPage parent) {
|
||||
public ExplorerSampleItem(File file, ExplorerPage parent) {
|
||||
super(file, parent);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.stardust.pio.PFile;
|
||||
import com.stardust.pio.PFiles;
|
||||
|
||||
import org.autojs.autojs.Pref;
|
||||
import org.autojs.autojs.model.sample.SampleFile;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
@@ -52,7 +53,7 @@ public class WorkspaceFileProvider extends ExplorerFileProvider {
|
||||
}
|
||||
} else {
|
||||
if (file.getPath().startsWith(mSampleDir.getPath())) {
|
||||
p.addChild(new ExplorerSamleItem(file, p));
|
||||
p.addChild(new ExplorerSampleItem(file, p));
|
||||
} else {
|
||||
p.addChild(new ExplorerFileItem(file, p));
|
||||
}
|
||||
@@ -98,6 +99,10 @@ public class WorkspaceFileProvider extends ExplorerFileProvider {
|
||||
});
|
||||
}
|
||||
|
||||
public static void resetSample(SampleFile sampleFile){
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ExplorerDirPage createExplorerPage(String path, ExplorerPage parent) {
|
||||
ExplorerDirPage page = super.createExplorerPage(path, parent);
|
||||
|
||||
@@ -12,10 +12,9 @@ import android.util.Pair;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.stardust.util.MapEntries;
|
||||
import com.stardust.util.MapBuilder;
|
||||
|
||||
import org.autojs.autojs.BuildConfig;
|
||||
import org.autojs.autojs.tool.EmptyObservers;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.SocketTimeoutException;
|
||||
@@ -24,7 +23,6 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import io.reactivex.subjects.PublishSubject;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
@@ -171,12 +169,12 @@ public class DevPluginService {
|
||||
|
||||
@WorkerThread
|
||||
private void sayHelloToServer(JsonWebSocket socket) throws IOException {
|
||||
writeMap(socket, TYPE_HELLO, new MapEntries<String, Object>()
|
||||
.entry("device_name", Build.BRAND + " " + Build.MODEL)
|
||||
.entry("client_version", CLIENT_VERSION)
|
||||
.entry("app_version", BuildConfig.VERSION_NAME)
|
||||
.entry("app_version_code", BuildConfig.VERSION_CODE)
|
||||
.map());
|
||||
writeMap(socket, TYPE_HELLO, new MapBuilder<String, Object>()
|
||||
.put("device_name", Build.BRAND + " " + Build.MODEL)
|
||||
.put("client_version", CLIENT_VERSION)
|
||||
.put("app_version", BuildConfig.VERSION_NAME)
|
||||
.put("app_version_code", BuildConfig.VERSION_CODE)
|
||||
.build());
|
||||
mHandshakeTimeoutHandler.postDelayed(() -> {
|
||||
if (mSocket != socket && !socket.isClosed()) {
|
||||
onHandshakeTimeout(socket);
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package org.autojs.autojs.storage.database;
|
||||
|
||||
|
||||
public abstract class BaseModel {
|
||||
private long mId;
|
||||
|
||||
public void setId(long id) {
|
||||
mId = id;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return mId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
BaseModel baseModel = (BaseModel) o;
|
||||
return mId == baseModel.mId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return (int)(mId ^ (mId >>> 32));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
package org.autojs.autojs.storage.database;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
|
||||
import org.autojs.autojs.timing.IntentTask;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import io.reactivex.Flowable;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import io.reactivex.subjects.PublishSubject;
|
||||
|
||||
public abstract class Database<M extends BaseModel> {
|
||||
|
||||
private final SQLiteDatabase mWritableSQLiteDatabase;
|
||||
private final SQLiteDatabase mReadableSQLiteDatabase;
|
||||
private final String mTable;
|
||||
private final PublishSubject<ModelChange<M>> mModelChange = PublishSubject.create();
|
||||
|
||||
public Database(SQLiteOpenHelper sqLiteOpenHelper, String table) {
|
||||
mWritableSQLiteDatabase = sqLiteOpenHelper.getWritableDatabase();
|
||||
mReadableSQLiteDatabase = sqLiteOpenHelper.getWritableDatabase();
|
||||
mTable = table;
|
||||
}
|
||||
|
||||
public <T> Observable<T> exec(Callable<T> callable) {
|
||||
return Observable.fromCallable(callable)
|
||||
.subscribeOn(Schedulers.io());
|
||||
}
|
||||
|
||||
public <T> Flowable<T> execFlowable(Callable<T> callable) {
|
||||
return Flowable.fromCallable(callable)
|
||||
.subscribeOn(Schedulers.io());
|
||||
}
|
||||
|
||||
public PublishSubject<ModelChange<M>> getModelChange() {
|
||||
return mModelChange;
|
||||
}
|
||||
|
||||
public Observable<Integer> delete(M model) {
|
||||
return exec(() -> {
|
||||
int delete = mWritableSQLiteDatabase.delete(mTable, "id = ?",
|
||||
new String[]{String.valueOf(model.getId())});
|
||||
if (delete >= 1) {
|
||||
mModelChange.onNext(new ModelChange<>(model, ModelChange.DELETE));
|
||||
}
|
||||
return delete;
|
||||
});
|
||||
}
|
||||
|
||||
public Observable<Integer> update(M model) {
|
||||
return exec(() -> {
|
||||
ContentValues values = asContentValues(model);
|
||||
int update = mWritableSQLiteDatabase.update(mTable, values, "id = ?", arg(model.getId()));
|
||||
if (update >= 1) {
|
||||
mModelChange.onNext(new ModelChange<>(model, ModelChange.UPDATE));
|
||||
}
|
||||
return update;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public Observable<Long> insert(M model) {
|
||||
return exec(() -> {
|
||||
ContentValues values = asContentValues(model);
|
||||
long id = mWritableSQLiteDatabase.insertOrThrow(mTable, null, values);
|
||||
if (id >= 0) {
|
||||
model.setId(id);
|
||||
mModelChange.onNext(new ModelChange<>(model, ModelChange.INSERT));
|
||||
}
|
||||
return id;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
protected abstract M createModelFromCursor(Cursor cursor);
|
||||
|
||||
protected abstract ContentValues asContentValues(M model);
|
||||
|
||||
public M queryById(long id) {
|
||||
Cursor cursor = mReadableSQLiteDatabase.rawQuery("SELECT * FROM " + mTable + " WHERE id = ?", arg(id));
|
||||
if (!cursor.moveToFirst()) {
|
||||
return null;
|
||||
}
|
||||
M model = createModelFromCursor(cursor);
|
||||
cursor.close();
|
||||
return model;
|
||||
}
|
||||
|
||||
|
||||
public Flowable<M> queryAllAsFlowable() {
|
||||
return execFlowable(() ->
|
||||
mReadableSQLiteDatabase.rawQuery("SELECT * FROM " + mTable, null)
|
||||
)
|
||||
.flatMap(cursor -> Flowable.fromIterable(() -> new CursorIterator(cursor)))
|
||||
.map(this::createModelFromCursor);
|
||||
}
|
||||
|
||||
public List<M> queryAll() {
|
||||
ArrayList<M> list = new ArrayList<>();
|
||||
Cursor cursor = mReadableSQLiteDatabase.rawQuery("SELECT * FROM " + mTable, null);
|
||||
while (cursor.moveToNext()) {
|
||||
list.add(createModelFromCursor(cursor));
|
||||
}
|
||||
cursor.close();
|
||||
return list;
|
||||
}
|
||||
|
||||
public long count() {
|
||||
Cursor cursor = mReadableSQLiteDatabase.rawQuery("SELECT COUNT(*) FROM " + mTable, null);
|
||||
if (cursor.moveToFirst()) {
|
||||
return cursor.getLong(0);
|
||||
}
|
||||
cursor.close();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
public Flowable<M> query(String sql, Object... args) {
|
||||
String[] strArgs = args(args);
|
||||
return execFlowable(() ->
|
||||
mReadableSQLiteDatabase.query(mTable, null, sql, strArgs, null, null, null)
|
||||
)
|
||||
.flatMap(cursor -> Flowable.fromIterable(() -> new CursorIterator(cursor)))
|
||||
.map(this::createModelFromCursor);
|
||||
}
|
||||
|
||||
private String[] args(Object[] args) {
|
||||
if (args == null || args.length == 0) {
|
||||
return null;
|
||||
}
|
||||
String[] a = new String[args.length];
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
a[i] = String.valueOf(args[i]);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
private String[] arg(Object value) {
|
||||
return new String[]{String.valueOf(value)};
|
||||
}
|
||||
|
||||
|
||||
private static class CursorIterator implements Iterator<Cursor> {
|
||||
|
||||
private final Cursor mCursor;
|
||||
|
||||
private CursorIterator(Cursor cursor) {
|
||||
mCursor = cursor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
boolean next = mCursor.moveToNext();
|
||||
if (!next) {
|
||||
mCursor.close();
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor next() {
|
||||
return mCursor;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,64 @@
|
||||
package org.autojs.autojs.storage.database;
|
||||
|
||||
import com.raizlabs.android.dbflow.annotation.Database;
|
||||
|
||||
@Database(version = 1)
|
||||
public class IntentTaskDatabase {
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
|
||||
import org.autojs.autojs.timing.IntentTask;
|
||||
|
||||
public class IntentTaskDatabase extends Database<IntentTask> {
|
||||
|
||||
private static final int VERSION = 1;
|
||||
private static final String NAME = "IntentTaskDatabase";
|
||||
|
||||
public IntentTaskDatabase(Context context){
|
||||
super(new SQLHelper(context), IntentTask.TABLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ContentValues asContentValues(IntentTask model) {
|
||||
ContentValues values = new ContentValues();
|
||||
values.put("script_path", model.getScriptPath());
|
||||
values.put("action", model.getAction());
|
||||
values.put("category", model.getCategory());
|
||||
values.put("data_type", model.getDataType());
|
||||
return values;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IntentTask createModelFromCursor(Cursor cursor) {
|
||||
IntentTask task = new IntentTask();
|
||||
task.setId(cursor.getInt(0));
|
||||
task.setScriptPath(cursor.getString(1));
|
||||
task.setAction(cursor.getString(2));
|
||||
task.setCategory(cursor.getString(3));
|
||||
task.setDataType(cursor.getString(4));
|
||||
return task;
|
||||
}
|
||||
|
||||
|
||||
private static class SQLHelper extends SQLiteOpenHelper {
|
||||
|
||||
public SQLHelper(Context context) {
|
||||
super(context, NAME + ".db", null, VERSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase db) {
|
||||
db.execSQL("CREATE TABLE `" + IntentTask.TABLE + "`(" +
|
||||
"`id` INTEGER PRIMARY KEY AUTOINCREMENT, " +
|
||||
"`script_path` TEXT NOT NULL ON CONFLICT FAIL, " +
|
||||
"`action` TEXT, " +
|
||||
"`category` TEXT, " +
|
||||
"`data_type` TEXT);");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package org.autojs.autojs.storage.database;
|
||||
|
||||
import com.raizlabs.android.dbflow.structure.BaseModel;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/11/28.
|
||||
@@ -8,10 +7,15 @@ import com.raizlabs.android.dbflow.structure.BaseModel;
|
||||
|
||||
public class ModelChange<M> {
|
||||
|
||||
private final M mData;
|
||||
private final BaseModel.Action mAction;
|
||||
public static final int INSERT = 1;
|
||||
public static final int UPDATE = 2;
|
||||
public static final int DELETE = 3;
|
||||
|
||||
public ModelChange(M data, BaseModel.Action action) {
|
||||
|
||||
private final M mData;
|
||||
private final int mAction;
|
||||
|
||||
public ModelChange(M data, int action) {
|
||||
mData = data;
|
||||
mAction = action;
|
||||
}
|
||||
@@ -20,7 +24,7 @@ public class ModelChange<M> {
|
||||
return mData;
|
||||
}
|
||||
|
||||
public BaseModel.Action getAction() {
|
||||
public int getAction() {
|
||||
return mAction;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,74 @@
|
||||
package org.autojs.autojs.storage.database;
|
||||
|
||||
import com.raizlabs.android.dbflow.annotation.Database;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/11/28.
|
||||
*/
|
||||
@Database(version = 1)
|
||||
public class TimedTaskDatabase {
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
|
||||
import org.autojs.autojs.timing.TimedTask;
|
||||
|
||||
public class TimedTaskDatabase extends Database<TimedTask> {
|
||||
|
||||
private static final int VERSION = 3;
|
||||
private static final String NAME = "TimedTaskDatabase";
|
||||
|
||||
public TimedTaskDatabase(Context context) {
|
||||
super(new SQLHelper(context), TimedTask.TABLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ContentValues asContentValues(TimedTask model) {
|
||||
ContentValues values = new ContentValues();
|
||||
values.put("time", model.getTimeFlag());
|
||||
values.put("scheduled", model.isScheduled());
|
||||
values.put("delay", model.getDelay());
|
||||
values.put("interval", model.getInterval());
|
||||
values.put("loop_times", model.getLoopTimes());
|
||||
values.put("millis", model.getMillis());
|
||||
values.put("script_path", model.getScriptPath());
|
||||
return values;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TimedTask createModelFromCursor(Cursor cursor) {
|
||||
TimedTask task = new TimedTask();
|
||||
task.setId(cursor.getInt(0));
|
||||
task.setTimeFlag(cursor.getLong(1));
|
||||
task.setScheduled(cursor.getInt(2) != 0);
|
||||
task.setDelay(cursor.getLong(3));
|
||||
task.setInterval(cursor.getLong(4));
|
||||
task.setLoopTimes(cursor.getInt(5));
|
||||
task.setMillis(cursor.getLong(6));
|
||||
task.setScriptPath(cursor.getString(7));
|
||||
return task;
|
||||
}
|
||||
|
||||
|
||||
private static class SQLHelper extends SQLiteOpenHelper {
|
||||
|
||||
public SQLHelper(Context context) {
|
||||
super(context, NAME + ".db", null, VERSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase db) {
|
||||
db.execSQL("CREATE TABLE `" + TimedTask.TABLE + "`(" +
|
||||
"`id` INTEGER PRIMARY KEY AUTOINCREMENT, " +
|
||||
"`time` INTEGER, " +
|
||||
"`scheduled` INTEGER, " +
|
||||
"`delay` INTEGER, " +
|
||||
"`interval` INTEGER, " +
|
||||
"`loop_times` INTEGER, " +
|
||||
"`millis` INTEGER, " +
|
||||
"`script_path` TEXT);");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,33 +2,19 @@ package org.autojs.autojs.timing;
|
||||
|
||||
import android.content.IntentFilter;
|
||||
|
||||
import com.raizlabs.android.dbflow.annotation.Column;
|
||||
import com.raizlabs.android.dbflow.annotation.NotNull;
|
||||
import com.raizlabs.android.dbflow.annotation.PrimaryKey;
|
||||
import com.raizlabs.android.dbflow.annotation.Table;
|
||||
import org.autojs.autojs.storage.database.BaseModel;
|
||||
|
||||
import org.autojs.autojs.storage.database.IntentTaskDatabase;
|
||||
import org.autojs.autojs.storage.database.TimedTaskDatabase;
|
||||
public class IntentTask extends BaseModel {
|
||||
|
||||
@Table(database = IntentTaskDatabase.class)
|
||||
public class IntentTask {
|
||||
public static final String TABLE = "IntentTask";
|
||||
|
||||
@PrimaryKey(autoincrement = true, quickCheckAutoIncrement = true)
|
||||
@Column(name = "id")
|
||||
int mId = -1;
|
||||
private String mScriptPath;
|
||||
|
||||
@NotNull
|
||||
@Column(name = "script_path")
|
||||
String mScriptPath;
|
||||
private String mAction;
|
||||
|
||||
@Column(name = "action")
|
||||
String mAction;
|
||||
private String mCategory;
|
||||
|
||||
@Column(name = "category")
|
||||
String mCategory;
|
||||
|
||||
@Column(name = "data_type")
|
||||
String mDataType;
|
||||
private String mDataType;
|
||||
|
||||
public IntentFilter getIntentFilter() {
|
||||
IntentFilter filter = new IntentFilter();
|
||||
@@ -48,14 +34,6 @@ public class IntentTask {
|
||||
return filter;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return mId;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
mId = id;
|
||||
}
|
||||
|
||||
public String getScriptPath() {
|
||||
return mScriptPath;
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ public class TaskReceiver extends BroadcastReceiver {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
ScriptIntents.handleIntent(context, intent);
|
||||
int id = intent.getIntExtra(EXTRA_TASK_ID, -1);
|
||||
long id = intent.getLongExtra(EXTRA_TASK_ID, -1);
|
||||
if (id >= 0) {
|
||||
TimedTaskManager.getInstance().notifyTaskFinished(id);
|
||||
}
|
||||
|
||||
@@ -4,13 +4,10 @@ import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import com.raizlabs.android.dbflow.annotation.Column;
|
||||
import com.raizlabs.android.dbflow.annotation.PrimaryKey;
|
||||
import com.raizlabs.android.dbflow.annotation.Table;
|
||||
import com.stardust.autojs.execution.ExecutionConfig;
|
||||
import org.autojs.autojs.external.ScriptIntents;
|
||||
import org.autojs.autojs.storage.database.TimedTaskDatabase;
|
||||
|
||||
import org.autojs.autojs.external.ScriptIntents;
|
||||
import org.autojs.autojs.storage.database.BaseModel;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.DateTimeConstants;
|
||||
import org.joda.time.LocalDateTime;
|
||||
@@ -19,11 +16,9 @@ import org.joda.time.LocalTime;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/11/27.
|
||||
*/
|
||||
@Table(database = TimedTaskDatabase.class)
|
||||
public class TimedTask {
|
||||
public class TimedTask extends BaseModel {
|
||||
|
||||
public static final String TABLE = "TimedTask";
|
||||
|
||||
private static final int FLAG_DISPOSABLE = 0;
|
||||
public final static int FLAG_SUNDAY = 0x1;
|
||||
@@ -36,29 +31,18 @@ public class TimedTask {
|
||||
private static final int FLAG_EVERYDAY = 0x7F;
|
||||
private static final int REQUEST_CODE = 2000;
|
||||
|
||||
@PrimaryKey(autoincrement = true, quickCheckAutoIncrement = true)
|
||||
@Column(name = "id")
|
||||
int mId = -1;
|
||||
|
||||
@Column(name = "time")
|
||||
long mTimeFlag;
|
||||
|
||||
@Column(name = "scheduled")
|
||||
boolean mScheduled;
|
||||
|
||||
@Column(name = "delay")
|
||||
long mDelay = 0;
|
||||
|
||||
@Column(name = "interval")
|
||||
long mInterval = 0;
|
||||
|
||||
@Column(name = "loop_times")
|
||||
int mLoopTimes = 1;
|
||||
|
||||
@Column(name = "millis")
|
||||
long mMillis;
|
||||
|
||||
@Column(name = "script_path")
|
||||
String mScriptPath;
|
||||
|
||||
public TimedTask() {
|
||||
@@ -148,19 +132,10 @@ public class TimedTask {
|
||||
return mMillis;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return mId;
|
||||
}
|
||||
|
||||
public String getScriptPath() {
|
||||
return mScriptPath;
|
||||
}
|
||||
|
||||
|
||||
public void setId(int id) {
|
||||
mId = id;
|
||||
}
|
||||
|
||||
public long getTimeFlag() {
|
||||
return mTimeFlag;
|
||||
}
|
||||
@@ -207,7 +182,7 @@ public class TimedTask {
|
||||
|
||||
public Intent createIntent() {
|
||||
return new Intent(TaskReceiver.ACTION_TASK)
|
||||
.putExtra(TaskReceiver.EXTRA_TASK_ID, mId)
|
||||
.putExtra(TaskReceiver.EXTRA_TASK_ID, getId())
|
||||
.putExtra(ScriptIntents.EXTRA_KEY_PATH, mScriptPath)
|
||||
.putExtra(ScriptIntents.EXTRA_KEY_DELAY, mDelay)
|
||||
.putExtra(ScriptIntents.EXTRA_KEY_LOOP_TIMES, mLoopTimes)
|
||||
@@ -216,14 +191,14 @@ public class TimedTask {
|
||||
|
||||
|
||||
public PendingIntent createPendingIntent(Context context) {
|
||||
return PendingIntent.getBroadcast(context, REQUEST_CODE + 1 + getId(),
|
||||
return PendingIntent.getBroadcast(context, (int) ((REQUEST_CODE + 1 + getId()) % 65535),
|
||||
createIntent(), PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TimedTask{" +
|
||||
"mId=" + mId +
|
||||
"mId=" + getId() +
|
||||
", mTimeFlag=" + mTimeFlag +
|
||||
", mScheduled=" + mScheduled +
|
||||
", mDelay=" + mDelay +
|
||||
@@ -234,20 +209,6 @@ public class TimedTask {
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
TimedTask timedTask = (TimedTask) o;
|
||||
|
||||
return mId == timedTask.mId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return mId;
|
||||
}
|
||||
|
||||
public static TimedTask dailyTask(LocalTime time, String scriptPath, ExecutionConfig config) {
|
||||
return new TimedTask(time.getMillisOfDay(), FLAG_EVERYDAY, scriptPath, config);
|
||||
|
||||
@@ -1,29 +1,22 @@
|
||||
package org.autojs.autojs.timing;
|
||||
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.raizlabs.android.dbflow.config.FlowManager;
|
||||
import com.raizlabs.android.dbflow.runtime.DirectModelNotifier;
|
||||
import com.raizlabs.android.dbflow.rx2.language.RXSQLite;
|
||||
import com.raizlabs.android.dbflow.sql.language.SQLite;
|
||||
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.App;
|
||||
import org.autojs.autojs.storage.database.IntentTaskDatabase;
|
||||
import org.autojs.autojs.storage.database.ModelChange;
|
||||
import org.autojs.autojs.storage.database.TimedTaskDatabase;
|
||||
import org.autojs.autojs.tool.EmptyObservers;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
import io.reactivex.Flowable;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import io.reactivex.subjects.PublishSubject;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/11/27.
|
||||
@@ -31,12 +24,10 @@ import io.reactivex.subjects.PublishSubject;
|
||||
//TODO rx
|
||||
public class TimedTaskManager {
|
||||
|
||||
|
||||
private static TimedTaskManager sInstance;
|
||||
private ModelAdapter<TimedTask> mTimedTaskModelAdapter;
|
||||
private ModelAdapter<IntentTask> mIntentTaskModelAdapter;
|
||||
private Context mContext;
|
||||
private PublishSubject<ModelChange<TimedTask>> mTimedTaskChanges = PublishSubject.create();
|
||||
private TimedTaskDatabase mTimedTaskDatabase;
|
||||
private IntentTaskDatabase mIntentTaskDatabase;
|
||||
|
||||
public static TimedTaskManager getInstance() {
|
||||
if (sInstance == null) {
|
||||
@@ -45,104 +36,132 @@ public class TimedTaskManager {
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
public TimedTaskManager(Context context) {
|
||||
mContext = context;
|
||||
mTimedTaskModelAdapter = FlowManager.getModelAdapter(TimedTask.class);
|
||||
mIntentTaskModelAdapter = FlowManager.getModelAdapter(IntentTask.class);
|
||||
DirectModelNotifier.get().registerForModelChanges(TimedTask.class, new DirectModelNotifier.ModelChangedListener<TimedTask>() {
|
||||
@Override
|
||||
public void onModelChanged(@NonNull TimedTask model, @NonNull BaseModel.Action action) {
|
||||
mTimedTaskChanges.onNext(new ModelChange<>(model, action));
|
||||
if (action == BaseModel.Action.DELETE && countTasks() == 0) {
|
||||
TimedTaskScheduler.stopRtcRepeating(mContext);
|
||||
} else if (action == BaseModel.Action.INSERT) {
|
||||
TimedTaskScheduler.checkTasksRepeatedlyIfNeeded(mContext);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTableChanged(@Nullable Class<?> tableChanged, @NonNull BaseModel.Action action) {
|
||||
|
||||
mTimedTaskDatabase = new TimedTaskDatabase(context);
|
||||
mIntentTaskDatabase = new IntentTaskDatabase(context);
|
||||
mTimedTaskDatabase.getModelChange().subscribe(change -> {
|
||||
int action = change.getAction();
|
||||
if (action == ModelChange.DELETE && countTasks() == 0) {
|
||||
TimedTaskScheduler.stopRtcRepeating(mContext);
|
||||
} else if (action == ModelChange.INSERT) {
|
||||
TimedTaskScheduler.checkTasksRepeatedlyIfNeeded(mContext);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void notifyTaskFinished(int id) {
|
||||
@SuppressLint("CheckResult")
|
||||
public void notifyTaskFinished(long id) {
|
||||
TimedTask task = getTimedTask(id);
|
||||
if (task == null)
|
||||
return;
|
||||
if (task.isDisposable()) {
|
||||
mTimedTaskModelAdapter.delete(task);
|
||||
mTimedTaskDatabase.delete(task)
|
||||
.subscribe(EmptyObservers.consumer(), Throwable::printStackTrace);
|
||||
} else {
|
||||
task.setScheduled(false);
|
||||
mTimedTaskModelAdapter.update(task);
|
||||
mTimedTaskDatabase.update(task)
|
||||
.subscribe(EmptyObservers.consumer(), Throwable::printStackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
public void removeTask(TimedTask timedTask) {
|
||||
TimedTaskScheduler.cancel(mContext, timedTask);
|
||||
mTimedTaskModelAdapter.delete(timedTask);
|
||||
mTimedTaskDatabase.delete(timedTask)
|
||||
.subscribe(EmptyObservers.consumer(), Throwable::printStackTrace);
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
public void addTask(TimedTask timedTask) {
|
||||
mTimedTaskModelAdapter.insert(timedTask);
|
||||
mTimedTaskDatabase.insert(timedTask)
|
||||
.subscribe(EmptyObservers.consumer(), Throwable::printStackTrace);;
|
||||
TimedTaskScheduler.scheduleTaskIfNeeded(mContext, timedTask);
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
public void addTask(IntentTask intentTask) {
|
||||
mIntentTaskModelAdapter.insert(intentTask);
|
||||
mIntentTaskDatabase.insert(intentTask)
|
||||
.subscribe(i -> {
|
||||
if(!TextUtils.isEmpty(intentTask.getAction())){
|
||||
App.getApp().getDynamicBroadcastReceivers()
|
||||
.register(intentTask.getAction());
|
||||
}
|
||||
}, Throwable::printStackTrace);
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
public void removeTask(IntentTask intentTask) {
|
||||
mIntentTaskModelAdapter.delete(intentTask);
|
||||
mIntentTaskDatabase.delete(intentTask)
|
||||
.subscribe(EmptyObservers.consumer(), Throwable::printStackTrace);;
|
||||
}
|
||||
|
||||
public Flowable<TimedTask> getAllTasks() {
|
||||
return RXSQLite.rx(SQLite.select().from(TimedTask.class))
|
||||
.queryStreamResults()
|
||||
.subscribeOn(Schedulers.io());
|
||||
return mTimedTaskDatabase.queryAllAsFlowable();
|
||||
}
|
||||
|
||||
public Flowable<IntentTask> getIntentTaskOfAction(String action) {
|
||||
IntentTask intentTask = new IntentTask();
|
||||
intentTask.setAction(Intent.ACTION_BOOT_COMPLETED);
|
||||
intentTask.setScriptPath(new File(Pref.getScriptDirPath(), "boot.js").getPath());
|
||||
return Flowable.just(intentTask);
|
||||
// return RXSQLite.rx(SQLite.select().from(IntentTask.class))
|
||||
// .queryStreamResults()
|
||||
// .subscribeOn(Schedulers.io());
|
||||
return mIntentTaskDatabase.query("action = ?", action);
|
||||
}
|
||||
|
||||
|
||||
public Observable<ModelChange<TimedTask>> getTimeTaskChanges() {
|
||||
return mTimedTaskChanges;
|
||||
return mTimedTaskDatabase.getModelChange();
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
public void notifyTaskScheduled(TimedTask timedTask) {
|
||||
timedTask.setScheduled(true);
|
||||
mTimedTaskModelAdapter.update(timedTask);
|
||||
mTimedTaskDatabase.update(timedTask)
|
||||
.subscribe(EmptyObservers.consumer(), Throwable::printStackTrace);
|
||||
|
||||
}
|
||||
|
||||
public List<TimedTask> getAllTasksAsList() {
|
||||
return SQLite.select().from(TimedTask.class)
|
||||
.queryList();
|
||||
return mTimedTaskDatabase.queryAll();
|
||||
}
|
||||
|
||||
public TimedTask getTimedTask(int taskId) {
|
||||
return SQLite.select()
|
||||
.from(TimedTask.class)
|
||||
.where(TimedTask_Table.id.is(taskId))
|
||||
.querySingle();
|
||||
public TimedTask getTimedTask(long taskId) {
|
||||
return mTimedTaskDatabase.queryById(taskId);
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
public void updateTask(TimedTask task) {
|
||||
mTimedTaskModelAdapter.update(task);
|
||||
mTimedTaskDatabase.update(task)
|
||||
.subscribe(EmptyObservers.consumer(), Throwable::printStackTrace);
|
||||
TimedTaskScheduler.cancel(mContext, task);
|
||||
TimedTaskScheduler.scheduleTaskIfNeeded(mContext, task);
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
public void updateTask(IntentTask task) {
|
||||
mIntentTaskDatabase.update(task)
|
||||
.subscribe(i -> {
|
||||
if(i > 0 && !TextUtils.isEmpty(task.getAction())){
|
||||
App.getApp().getDynamicBroadcastReceivers()
|
||||
.register(task.getAction());
|
||||
}
|
||||
}, Throwable::printStackTrace);
|
||||
}
|
||||
|
||||
public long countTasks() {
|
||||
return SQLite.select().from(TimedTask.class).count();
|
||||
return mTimedTaskDatabase.count();
|
||||
}
|
||||
|
||||
public List<IntentTask> getAllIntentTasksAsList() {
|
||||
return mIntentTaskDatabase.queryAll();
|
||||
}
|
||||
|
||||
public Observable<ModelChange<IntentTask>> getIntentTaskChanges() {
|
||||
return mIntentTaskDatabase.getModelChange();
|
||||
}
|
||||
|
||||
public IntentTask getIntentTask(long intentTaskId) {
|
||||
return mIntentTaskDatabase.queryById(intentTaskId);
|
||||
}
|
||||
|
||||
public Flowable<IntentTask> getAllIntentTasks() {
|
||||
return mIntentTaskDatabase.queryAllAsFlowable();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ public class TimedTaskScheduler extends BroadcastReceiver {
|
||||
private static final long INTERVAL = TimeUnit.MINUTES.toMillis(1);
|
||||
private static final long ONE_HOUR = TimeUnit.HOURS.toMillis(1);
|
||||
private static PendingIntent sCheckTasksPendingIntent;
|
||||
private static long mNextRtcWakeupMillis = -1;
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
@@ -38,7 +37,7 @@ public class TimedTaskScheduler extends BroadcastReceiver {
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
private static void checkTasks(Context context) {
|
||||
public static void checkTasks(Context context) {
|
||||
TimedTaskManager.getInstance().getAllTasks()
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
@@ -83,7 +82,7 @@ public class TimedTaskScheduler extends BroadcastReceiver {
|
||||
|
||||
|
||||
public static void checkTasksRepeatedlyIfNeeded(Context context) {
|
||||
if (TimedTaskManager.getInstance().countTasks() > 0 && mNextRtcWakeupMillis > 0) {
|
||||
if (TimedTaskManager.getInstance().countTasks() > 0) {
|
||||
setupNextRtcWakeup(context, System.currentTimeMillis() + 5000);
|
||||
}
|
||||
}
|
||||
@@ -95,7 +94,6 @@ public class TimedTaskScheduler extends BroadcastReceiver {
|
||||
}
|
||||
AlarmManager alarmManager = getAlarmManager(context);
|
||||
setExactCompat(alarmManager, createTaskCheckPendingIntent(context), millis);
|
||||
mNextRtcWakeupMillis = millis;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.stardust.app.GlobalAppContext;
|
||||
import com.stardust.pio.PFile;
|
||||
import com.stardust.pio.PFiles;
|
||||
import com.stardust.pio.UncheckedIOException;
|
||||
import com.tencent.bugly.crashreport.BuglyLog;
|
||||
|
||||
import org.autojs.autojs.Pref;
|
||||
import org.autojs.autojs.R;
|
||||
@@ -122,7 +123,11 @@ public class ScriptOperations {
|
||||
}
|
||||
|
||||
private void notifyFileCreated(ScriptFile directory, ScriptFile scriptFile) {
|
||||
mExplorer.notifyItemCreated(new ExplorerFileItem(scriptFile, mExplorerPage));
|
||||
if (scriptFile.isDirectory()) {
|
||||
mExplorer.notifyItemCreated(new ExplorerDirPage(scriptFile, mExplorerPage));
|
||||
} else {
|
||||
mExplorer.notifyItemCreated(new ExplorerFileItem(scriptFile, mExplorerPage));
|
||||
}
|
||||
}
|
||||
|
||||
public void newFile() {
|
||||
@@ -315,9 +320,11 @@ public class ScriptOperations {
|
||||
|
||||
|
||||
public Observable<ScriptFile> download(String url) {
|
||||
BuglyLog.i(LOG_TAG, "dir = " + Pref.getScriptDirPath() + ", sdcard = " + Environment.getExternalStorageDirectory() + ", url = " + url);
|
||||
String fileName = DownloadManager.parseFileNameLocally(url);
|
||||
return new FileChooserDialogBuilder(mContext)
|
||||
.title(R.string.text_select_save_path)
|
||||
.dir(Pref.getScriptDirPath())
|
||||
.chooseDir()
|
||||
.singleChoice()
|
||||
.map(saveDir -> new File(saveDir, fileName).getPath())
|
||||
|
||||
@@ -74,23 +74,12 @@ public class DocsFragment extends ViewPagerFragment implements BackPressedHandle
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
((BackPressedHandler.HostActivity) getActivity())
|
||||
.getBackPressedObserver()
|
||||
.registerHandlerAtFront(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
Bundle savedWebViewState = new Bundle();
|
||||
mWebView.saveState(savedWebViewState);
|
||||
getArguments().putBundle("savedWebViewState", savedWebViewState);
|
||||
((BackPressedHandler.HostActivity) getActivity())
|
||||
.getBackPressedObserver()
|
||||
.unregisterHandler(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -180,6 +180,7 @@ EditActivity extends BaseActivity implements OnActivityResultDelegate.DelegateHo
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
mEditorView.destroy();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
|
||||
@@ -392,7 +392,7 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
|
||||
Snackbar.make(this, R.string.text_start_running, Snackbar.LENGTH_SHORT).show();
|
||||
}
|
||||
ScriptExecution execution = Scripts.runWithBroadcastSender(mFile);
|
||||
if(execution == null){
|
||||
if (execution == null) {
|
||||
return null;
|
||||
}
|
||||
mScriptExecutionId = execution.getId();
|
||||
@@ -671,4 +671,9 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
|
||||
super.onRestoreInstanceState(superData);
|
||||
setMenuItemStatus(R.id.run, mScriptExecutionId == ScriptExecution.NO_ID);
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
mEditor.destroy();
|
||||
mAutoCompletion.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -373,6 +373,11 @@ public class CodeEditor extends HVScrollView {
|
||||
mCodeEditText.removeAllBreakpoints();
|
||||
}
|
||||
|
||||
public void destroy(){
|
||||
mJavaScriptHighlighter.shutdown();
|
||||
mJsBeautifier.shutdown();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
int codeWidth = getWidth() - getPaddingLeft() - getPaddingRight();
|
||||
|
||||
@@ -2,10 +2,12 @@ package org.autojs.autojs.ui.edit.editor;
|
||||
|
||||
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.TimingLogger;
|
||||
|
||||
import com.stardust.autojs.rhino.TokenStream;
|
||||
import com.stardust.pio.UncheckedIOException;
|
||||
|
||||
import org.autojs.autojs.ui.edit.theme.Theme;
|
||||
import org.autojs.autojs.ui.widget.SimpleTextWatcher;
|
||||
|
||||
@@ -46,7 +48,7 @@ public class JavaScriptHighlighter implements SimpleTextWatcher.AfterTextChanged
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString() + "{count = " + mCount + ", length = " + mText.length() + "}";
|
||||
return super.toString() + "{count = " + mCount + ", length = " + mText.length() + "}";
|
||||
}
|
||||
|
||||
public int getCharCount() {
|
||||
@@ -60,16 +62,18 @@ public class JavaScriptHighlighter implements SimpleTextWatcher.AfterTextChanged
|
||||
|
||||
private Theme mTheme;
|
||||
private CodeEditText mCodeEditText;
|
||||
private ThreadPoolExecutor mExecutorService = new ThreadPoolExecutor(3, 6,
|
||||
private ThreadPoolExecutor mExecutorService = new ThreadPoolExecutor(3, 6,
|
||||
2L, TimeUnit.MINUTES, new LinkedBlockingQueue<>());
|
||||
private AtomicInteger mRunningHighlighterId = new AtomicInteger();
|
||||
private TimingLogger mLogger = new TimingLogger(CodeEditText.LOG_TAG, "highlight");
|
||||
private final TextWatcher mTextWatcher;
|
||||
|
||||
public JavaScriptHighlighter(Theme theme, CodeEditText codeEditText) {
|
||||
mExecutorService.allowCoreThreadTimeOut(true);
|
||||
mTheme = theme;
|
||||
mCodeEditText = codeEditText;
|
||||
codeEditText.addTextChangedListener(new SimpleTextWatcher(this));
|
||||
mTextWatcher = new SimpleTextWatcher(this);
|
||||
codeEditText.addTextChangedListener(mTextWatcher);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -112,5 +116,9 @@ public class JavaScriptHighlighter implements SimpleTextWatcher.AfterTextChanged
|
||||
mCodeEditText.updateHighlightTokens(highlightTokens);
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
mCodeEditText.removeTextChangedListener(mTextWatcher);
|
||||
mExecutorService.shutdownNow();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,290 +0,0 @@
|
||||
package org.autojs.autojs.ui.edit.editor;
|
||||
/*
|
||||
* Copyright 2016. SHENQINCI(沈钦赐)<946736079@qq.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.widget.EditText;
|
||||
|
||||
import java.util.Stack;
|
||||
|
||||
/**
|
||||
* 撤销和恢复撤销
|
||||
* Created by 沈钦赐 on 16/6/23.
|
||||
*/
|
||||
public class TextViewRedoUndoer {
|
||||
//操作序号(一次编辑可能对应多个操作,如替换文字,就是删除+插入)
|
||||
int index;
|
||||
//撤销栈
|
||||
Stack<Action> history = new Stack<>();
|
||||
//恢复栈
|
||||
Stack<Action> historyBack = new Stack<>();
|
||||
|
||||
private Editable editable;
|
||||
private EditText editText;
|
||||
//自动操作标志,防止重复回调,导致无限撤销
|
||||
private boolean flag = false;
|
||||
|
||||
private int mInitialHistoryStackSize;
|
||||
private boolean mEnabled = true;
|
||||
|
||||
public TextViewRedoUndoer(@NonNull EditText editText) {
|
||||
this.editable = editText.getText();
|
||||
this.editText = editText;
|
||||
editText.addTextChangedListener(new Watcher());
|
||||
}
|
||||
|
||||
protected void onEditableChanged(Editable s) {
|
||||
|
||||
}
|
||||
|
||||
protected void onTextChanged(Editable s) {
|
||||
if (history.size() < mInitialHistoryStackSize) {
|
||||
mInitialHistoryStackSize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 清理记录
|
||||
* Clear history.
|
||||
*/
|
||||
public final void clearHistory() {
|
||||
history.clear();
|
||||
historyBack.clear();
|
||||
mInitialHistoryStackSize = 0;
|
||||
}
|
||||
|
||||
public boolean canUndo() {
|
||||
return !history.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* 撤销
|
||||
* Undo.
|
||||
*/
|
||||
public final void undo() {
|
||||
if (history.empty()) return;
|
||||
//锁定操作
|
||||
flag = true;
|
||||
Action action = history.pop();
|
||||
historyBack.push(action);
|
||||
if (action.isAdd) {
|
||||
//撤销添加
|
||||
editable.delete(action.startCursor, action.startCursor + action.actionTarget.length());
|
||||
editText.setSelection(action.startCursor, action.startCursor);
|
||||
} else {
|
||||
//插销删除
|
||||
editable.insert(action.startCursor, action.actionTarget);
|
||||
if (action.endCursor == action.startCursor) {
|
||||
editText.setSelection(action.startCursor + action.actionTarget.length());
|
||||
} else {
|
||||
editText.setSelection(action.startCursor, action.endCursor);
|
||||
}
|
||||
}
|
||||
//释放操作
|
||||
flag = false;
|
||||
//判断是否是下一个动作是否和本动作是同一个操作,直到不同为止
|
||||
if (!history.empty() && history.peek().index == action.index) {
|
||||
undo();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean canRedo() {
|
||||
return !historyBack.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* 恢复
|
||||
* Redo.
|
||||
*/
|
||||
public final void redo() {
|
||||
if (historyBack.empty()) return;
|
||||
flag = true;
|
||||
Action action = historyBack.pop();
|
||||
history.push(action);
|
||||
if (action.isAdd) {
|
||||
//恢复添加
|
||||
editable.insert(action.startCursor, action.actionTarget);
|
||||
if (action.endCursor == action.startCursor) {
|
||||
editText.setSelection(action.startCursor + action.actionTarget.length());
|
||||
} else {
|
||||
editText.setSelection(action.startCursor, action.endCursor);
|
||||
}
|
||||
} else {
|
||||
//恢复删除
|
||||
editable.delete(action.startCursor, action.startCursor + action.actionTarget.length());
|
||||
editText.setSelection(action.startCursor, action.startCursor);
|
||||
}
|
||||
flag = false;
|
||||
//判断是否是下一个动作是否和本动作是同一个操作
|
||||
if (!historyBack.empty() && historyBack.peek().index == action.index)
|
||||
redo();
|
||||
}
|
||||
|
||||
/**
|
||||
* 首次设置文本
|
||||
* Set default text.
|
||||
*/
|
||||
public final void setDefaultText(CharSequence text) {
|
||||
clearHistory();
|
||||
flag = true;
|
||||
editable.replace(0, editable.length(), text);
|
||||
flag = false;
|
||||
}
|
||||
|
||||
public boolean isTextChanged() {
|
||||
return history.size() != mInitialHistoryStackSize;
|
||||
}
|
||||
|
||||
public void markTextAsUnchanged() {
|
||||
mInitialHistoryStackSize = history.size();
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
mEnabled = enabled;
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return mEnabled;
|
||||
}
|
||||
|
||||
private class Watcher implements TextWatcher {
|
||||
|
||||
/**
|
||||
* Before text changed.
|
||||
*
|
||||
* @param s the s
|
||||
* @param start the start 起始光标
|
||||
* @param count the endCursor 选择数量
|
||||
* @param after the after 替换增加的文字数
|
||||
*/
|
||||
@Override
|
||||
public final void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
if (!editText.isEnabled() || !mEnabled) {
|
||||
return;
|
||||
}
|
||||
if (flag) return;
|
||||
int end = start + count;
|
||||
if (end > start && end <= s.length()) {
|
||||
CharSequence charSequence = s.subSequence(start, end);
|
||||
//删除了文字
|
||||
if (charSequence.length() > 0) {
|
||||
Action action = new Action(charSequence, start, false);
|
||||
if (count > 1) {
|
||||
//如果一次超过一个字符,说名用户选择了,然后替换或者删除操作
|
||||
action.setSelectCount(count);
|
||||
} else if (count == 1 && count == after) {
|
||||
//一个字符替换
|
||||
action.setSelectCount(count);
|
||||
}
|
||||
//还有一种情况:选择一个字符,然后删除(暂时没有考虑这种情况)
|
||||
|
||||
history.push(action);
|
||||
historyBack.clear();
|
||||
action.setIndex(++index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* On text changed.
|
||||
*
|
||||
* @param s the s
|
||||
* @param start the start 起始光标
|
||||
* @param before the before 选择数量
|
||||
* @param count the endCursor 添加的数量
|
||||
*/
|
||||
@Override
|
||||
public final void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
if (!editText.isEnabled() || !mEnabled) {
|
||||
return;
|
||||
}
|
||||
if (flag) return;
|
||||
int end = start + count;
|
||||
if (end > start) {
|
||||
CharSequence charSequence = s.subSequence(start, end);
|
||||
//添加文字
|
||||
if (charSequence.length() > 0) {
|
||||
Action action = new Action(charSequence, start, true);
|
||||
|
||||
history.push(action);
|
||||
historyBack.clear();
|
||||
if (before > 0) {
|
||||
//文字替换(先删除再增加),删除和增加是同一个操作,所以不需要增加序号
|
||||
action.setIndex(index);
|
||||
} else {
|
||||
action.setIndex(++index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void afterTextChanged(Editable s) {
|
||||
if (!editText.isEnabled() || !mEnabled) {
|
||||
return;
|
||||
}
|
||||
if (flag) return;
|
||||
if (s != editable) {
|
||||
editable = s;
|
||||
onEditableChanged(s);
|
||||
}
|
||||
TextViewRedoUndoer.this.onTextChanged(s);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class Action {
|
||||
/**
|
||||
* 改变字符.
|
||||
*/
|
||||
CharSequence actionTarget;
|
||||
/**
|
||||
* 光标位置.
|
||||
*/
|
||||
int startCursor;
|
||||
int endCursor;
|
||||
/**
|
||||
* 标志增加操作.
|
||||
*/
|
||||
boolean isAdd;
|
||||
/**
|
||||
* 操作序号.
|
||||
*/
|
||||
int index;
|
||||
|
||||
|
||||
public Action(CharSequence actionTag, int startCursor, boolean add) {
|
||||
this.actionTarget = actionTag;
|
||||
this.startCursor = startCursor;
|
||||
this.endCursor = startCursor;
|
||||
this.isAdd = add;
|
||||
}
|
||||
|
||||
public void setSelectCount(int count) {
|
||||
this.endCursor = endCursor + count;
|
||||
}
|
||||
|
||||
public void setIndex(int index) {
|
||||
this.index = index;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import java.util.LinkedList;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.Editor;
|
||||
import android.os.Handler;
|
||||
import android.text.Editable;
|
||||
import android.text.Selection;
|
||||
import android.text.TextWatcher;
|
||||
@@ -46,6 +47,10 @@ public class TextViewUndoRedo {
|
||||
|
||||
private int mInitialHistoryStackSize;
|
||||
|
||||
private Handler mHandler = new Handler();
|
||||
private int mTextChangeId = 0;
|
||||
private boolean mTextChanging = false;
|
||||
|
||||
// =================================================================== //
|
||||
|
||||
/**
|
||||
@@ -404,7 +409,6 @@ public class TextViewUndoRedo {
|
||||
if (mIsUndoOrRedo || !mEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
mBeforeChange = s.subSequence(start, start + count);
|
||||
}
|
||||
|
||||
@@ -415,7 +419,10 @@ public class TextViewUndoRedo {
|
||||
}
|
||||
|
||||
mAfterChange = s.subSequence(start, start + count);
|
||||
mTextChangeId++;
|
||||
mEditHistory.add(new EditItem(start, mBeforeChange, mAfterChange));
|
||||
int textChangeId = mTextChangeId;
|
||||
//TODO 增加连续输入文字当成一次撤销的功能
|
||||
}
|
||||
|
||||
public void afterTextChanged(Editable s) {
|
||||
|
||||
@@ -4,9 +4,6 @@ import android.content.Context;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.widget.CardView;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
@@ -14,7 +11,6 @@ import com.stardust.autojs.project.ProjectConfig;
|
||||
import com.stardust.autojs.project.ProjectLauncher;
|
||||
import com.stardust.pio.PFile;
|
||||
|
||||
import org.androidannotations.annotations.Click;
|
||||
import org.autojs.autojs.R;
|
||||
import org.autojs.autojs.autojs.AutoJs;
|
||||
import org.autojs.autojs.model.explorer.ExplorerChangeEvent;
|
||||
@@ -59,15 +55,19 @@ public class ExplorerProjectToolbar extends CardView {
|
||||
setOnClickListener(view -> edit());
|
||||
}
|
||||
|
||||
public void setProject(PFile dir, ProjectConfig config) {
|
||||
public void setProject(PFile dir) {
|
||||
mProjectConfig = ProjectConfig.fromProjectDir(dir.getPath());
|
||||
if(mProjectConfig == null){
|
||||
setVisibility(GONE);
|
||||
return;
|
||||
}
|
||||
mDirectory = dir;
|
||||
mProjectConfig = config;
|
||||
mProjectName.setText(config.getName());
|
||||
mProjectName.setText(mProjectConfig.getName());
|
||||
}
|
||||
|
||||
public void refresh() {
|
||||
if (mDirectory != null) {
|
||||
setProject(mDirectory, ProjectConfig.fromProjectDir(mDirectory.getPath()));
|
||||
setProject(mDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,11 @@ 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.ExplorerProjectPage;
|
||||
import org.autojs.autojs.model.explorer.ExplorerSampleItem;
|
||||
import org.autojs.autojs.model.explorer.ExplorerSamplePage;
|
||||
import org.autojs.autojs.model.explorer.Explorers;
|
||||
import org.autojs.autojs.model.explorer.WorkspaceFileProvider;
|
||||
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.ui.project.BuildActivity;
|
||||
@@ -111,7 +115,7 @@ public class ExplorerView extends ThemeColorSwipeRefreshLayout implements SwipeR
|
||||
mCurrentPageState = currentPageState;
|
||||
if (mCurrentPageState.page instanceof ExplorerProjectPage) {
|
||||
mProjectToolbar.setVisibility(VISIBLE);
|
||||
mProjectToolbar.setProject(currentPageState.page.toScriptFile(), ((ExplorerProjectPage) currentPageState.page).getProjectConfig());
|
||||
mProjectToolbar.setProject(currentPageState.page.toScriptFile());
|
||||
} else {
|
||||
mProjectToolbar.setVisibility(GONE);
|
||||
}
|
||||
@@ -306,6 +310,8 @@ public class ExplorerView extends ThemeColorSwipeRefreshLayout implements SwipeR
|
||||
case R.id.action_sort_by_size:
|
||||
sort(ExplorerItemList.SORT_TYPE_SIZE, mDirSortMenuShowing);
|
||||
break;
|
||||
case R.id.reset:
|
||||
// WorkspaceFileProvider.resetSample(mSelectedItem.toScriptFile());
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -487,6 +493,9 @@ public class ExplorerView extends ThemeColorSwipeRefreshLayout implements SwipeR
|
||||
}
|
||||
if (!mExplorerItem.canRename()) {
|
||||
menu.removeItem(R.id.rename);
|
||||
}
|
||||
if(mExplorerItem instanceof ExplorerSampleItem){
|
||||
|
||||
}
|
||||
popupMenu.setOnMenuItemClickListener(ExplorerView.this);
|
||||
popupMenu.show();
|
||||
|
||||
@@ -6,6 +6,7 @@ import android.support.annotation.StringRes;
|
||||
|
||||
import com.afollestad.materialdialogs.MaterialDialog;
|
||||
import com.stardust.pio.PFile;
|
||||
import com.tencent.bugly.crashreport.BuglyLog;
|
||||
|
||||
import org.autojs.autojs.R;
|
||||
import org.autojs.autojs.model.explorer.Explorer;
|
||||
@@ -66,7 +67,6 @@ public class FileChooserDialogBuilder extends ThemeColorMaterialDialogBuilder {
|
||||
public FileChooserDialogBuilder dir(String rootDir, String initialDir) {
|
||||
mRootDir = rootDir;
|
||||
mInitialDir = initialDir;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@ public class CircularMenu implements Recorder.OnStateChangedListener, LayoutInsp
|
||||
@Override
|
||||
public View inflateActionView(FloatyService service, CircularMenuWindow window) {
|
||||
View actionView = View.inflate(service, R.layout.circular_action_view, null);
|
||||
mActionViewIcon = (RoundedImageView) actionView.findViewById(R.id.icon);
|
||||
mActionViewIcon = actionView.findViewById(R.id.icon);
|
||||
return actionView;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
package org.autojs.autojs.ui.floating;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorEvent;
|
||||
import android.hardware.SensorEventListener;
|
||||
import android.util.Log;
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.view.OrientationEventListener;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
@@ -15,9 +12,13 @@ import com.stardust.enhancedfloaty.FloatyWindow;
|
||||
import com.stardust.enhancedfloaty.WindowBridge;
|
||||
import com.stardust.floatingcircularactionmenu.CircularActionMenu;
|
||||
import com.stardust.floatingcircularactionmenu.gesture.BounceDragGesture;
|
||||
import com.stardust.util.ScreenMetrics;
|
||||
|
||||
public class CircularMenuWindow implements FloatyWindow {
|
||||
|
||||
private static final String KEY_POSITION_X = CircularMenuWindow.class.getName() + ".position.x";
|
||||
private static final String KEY_POSITION_Y = CircularMenuWindow.class.getName() + ".position.y";
|
||||
|
||||
protected CircularMenuFloaty mFloaty;
|
||||
protected WindowManager mWindowManager;
|
||||
protected CircularActionMenu mCircularActionMenu;
|
||||
@@ -66,6 +67,9 @@ public class CircularMenuWindow implements FloatyWindow {
|
||||
}
|
||||
|
||||
private void setInitialState() {
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(mContext);
|
||||
int y = preferences.getInt(KEY_POSITION_Y, ScreenMetrics.getDeviceScreenHeight() / 2);
|
||||
mActionViewWindowBridge.updatePosition(mActionViewWindowBridge.getX(), y);
|
||||
keepToSide();
|
||||
}
|
||||
|
||||
@@ -190,6 +194,11 @@ public class CircularMenuWindow implements FloatyWindow {
|
||||
}
|
||||
|
||||
public void close() {
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(mContext);
|
||||
preferences.edit()
|
||||
.putInt(KEY_POSITION_X, mActionViewWindowBridge.getX())
|
||||
.putInt(KEY_POSITION_Y, mActionViewWindowBridge.getY())
|
||||
.apply();
|
||||
mOrientationEventListener.disable();
|
||||
this.mWindowManager.removeView(this.mCircularActionMenu);
|
||||
this.mWindowManager.removeView(this.mCircularActionView);
|
||||
|
||||
@@ -37,6 +37,7 @@ 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.external.foreground.ForegroundService;
|
||||
import org.autojs.autojs.model.explorer.Explorers;
|
||||
import org.autojs.autojs.tool.AccessibilityServiceTool;
|
||||
import org.autojs.autojs.ui.BaseActivity;
|
||||
@@ -208,6 +209,7 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega
|
||||
public void exitCompletely() {
|
||||
finish();
|
||||
FloatyWindowManger.hideCircularMenu();
|
||||
ForegroundService.stop(this);
|
||||
stopService(new Intent(this, FloatyService.class));
|
||||
AutoJs.getInstance().getScriptEngineService().stopAll();
|
||||
}
|
||||
@@ -264,6 +266,12 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
Fragment fragment = mPagerAdapter.getStoredFragment(mViewPager.getCurrentItem());
|
||||
if (fragment instanceof BackPressedHandler) {
|
||||
if (((BackPressedHandler) fragment).onBackPressed(this)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!mBackPressObserver.onBackPressed(this)) {
|
||||
super.onBackPressed();
|
||||
}
|
||||
|
||||
@@ -3,14 +3,17 @@ package org.autojs.autojs.ui.main;
|
||||
import android.support.annotation.CallSuper;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.view.animation.FastOutSlowInInterpolator;
|
||||
import android.view.View;
|
||||
|
||||
import com.stardust.util.BackPressedHandler;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/8/22.
|
||||
*/
|
||||
|
||||
public abstract class ViewPagerFragment extends Fragment {
|
||||
public abstract class ViewPagerFragment extends Fragment implements BackPressedHandler {
|
||||
|
||||
protected static final int ROTATION_GONE = -1;
|
||||
|
||||
|
||||
@@ -72,23 +72,12 @@ public class CommunityFragment extends ViewPagerFragment implements BackPressedH
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
((BackPressedHandler.HostActivity) getActivity())
|
||||
.getBackPressedObserver()
|
||||
.registerHandlerAtFront(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
Bundle savedWebViewState = new Bundle();
|
||||
mWebView.saveState(savedWebViewState);
|
||||
getArguments().putBundle("savedWebViewState", savedWebViewState);
|
||||
((BackPressedHandler.HostActivity) getActivity())
|
||||
.getBackPressedObserver()
|
||||
.unregisterHandler(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.autojs.autojs.ui.main.drawer;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Intent;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
@@ -22,6 +23,7 @@ import com.stardust.notification.NotificationListenerService;
|
||||
|
||||
import org.autojs.autojs.Pref;
|
||||
import org.autojs.autojs.R;
|
||||
import org.autojs.autojs.external.foreground.ForegroundService;
|
||||
import org.autojs.autojs.network.GlideApp;
|
||||
import org.autojs.autojs.network.UserService;
|
||||
import org.autojs.autojs.tool.EmptyObservers;
|
||||
@@ -107,6 +109,8 @@ public class DrawerFragment extends android.support.v4.app.Fragment {
|
||||
};
|
||||
|
||||
private DrawerMenuItem mNotificationPermissionItem = new DrawerMenuItem(R.drawable.ic_ali_notification, R.string.text_notification_permission, 0, this::goToNotificationServiceSettings);
|
||||
private DrawerMenuItem mForegroundServiceItem = new DrawerMenuItem(R.drawable.ic_service_green, R.string.text_foreground_service, R.string.key_foreground_servie, this::toggleForegroundService);
|
||||
|
||||
private DrawerMenuItem mFloatingWindowItem = new DrawerMenuItem(R.drawable.ic_robot_64, R.string.text_floating_window, 0, this::showOrDismissFloatingWindow);
|
||||
private DrawerMenuItem mCheckForUpdatesItem = new DrawerMenuItem(R.drawable.ic_check_for_updates, R.string.text_check_for_updates, this::checkForUpdates);
|
||||
|
||||
@@ -142,6 +146,10 @@ public class DrawerFragment extends android.support.v4.app.Fragment {
|
||||
setChecked(mFloatingWindowItem, true);
|
||||
}
|
||||
setChecked(mConnectionItem, DevPluginService.getInstance().isConnected());
|
||||
if(Pref.isForegroundServiceEnabled()){
|
||||
ForegroundService.start(GlobalAppContext.get());
|
||||
setChecked(mForegroundServiceItem, true);
|
||||
}
|
||||
}
|
||||
|
||||
private void initMenuItems() {
|
||||
@@ -150,6 +158,7 @@ public class DrawerFragment extends android.support.v4.app.Fragment {
|
||||
mAccessibilityServiceItem,
|
||||
mStableModeItem,
|
||||
mNotificationPermissionItem,
|
||||
mForegroundServiceItem,
|
||||
|
||||
new DrawerMenuGroup(R.string.text_script_record),
|
||||
mFloatingWindowItem,
|
||||
@@ -165,6 +174,7 @@ public class DrawerFragment extends android.support.v4.app.Fragment {
|
||||
}
|
||||
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
@Click(R.id.avatar)
|
||||
void loginOrShowUserInfo() {
|
||||
UserService.getInstance()
|
||||
@@ -251,6 +261,17 @@ public class DrawerFragment extends android.support.v4.app.Fragment {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void toggleForegroundService(DrawerMenuItemViewHolder holder) {
|
||||
boolean checked = holder.getSwitchCompat().isChecked();
|
||||
if(checked){
|
||||
ForegroundService.start(GlobalAppContext.get());
|
||||
}else {
|
||||
ForegroundService.stop(GlobalAppContext.get());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void inputRemoteHost() {
|
||||
String host = Pref.getServerAddressOrDefault(WifiTool.getRouterIp(getActivity()));
|
||||
new MaterialDialog.Builder(getActivity())
|
||||
|
||||
@@ -62,7 +62,6 @@ public class MarketFragment extends ViewPagerFragment implements BackPressedHand
|
||||
|
||||
@Override
|
||||
public boolean onBackPressed(Activity activity) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,9 @@ import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
|
||||
import com.stardust.app.GlobalAppContext;
|
||||
import com.stardust.util.BackPressedHandler;
|
||||
import com.stardust.util.IntentUtil;
|
||||
|
||||
@@ -26,6 +28,7 @@ import org.autojs.autojs.ui.main.ViewPagerFragment;
|
||||
import org.autojs.autojs.ui.project.ProjectConfigActivity;
|
||||
import org.autojs.autojs.ui.project.ProjectConfigActivity_;
|
||||
import org.autojs.autojs.ui.viewmodel.ExplorerItemList;
|
||||
import org.autojs.autojs.ui.widget.ExpandableRecyclerView;
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
|
||||
@@ -35,7 +38,7 @@ import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
* Created by Stardust on 2017/3/13.
|
||||
*/
|
||||
@EFragment(R.layout.fragment_my_script_list)
|
||||
public class MyScriptListFragment extends ViewPagerFragment implements BackPressedHandler, FloatingActionMenu.OnFloatingActionButtonClickListener {
|
||||
public class MyScriptListFragment extends ViewPagerFragment implements FloatingActionMenu.OnFloatingActionButtonClickListener {
|
||||
|
||||
private static final String TAG = "MyScriptListFragment";
|
||||
|
||||
@@ -63,27 +66,11 @@ public class MyScriptListFragment extends ViewPagerFragment implements BackPress
|
||||
if (item.isEditable()) {
|
||||
Scripts.edit(item.toScriptFile());
|
||||
} else {
|
||||
IntentUtil.viewFile(getContext(), item.getPath());
|
||||
IntentUtil.viewFile(GlobalAppContext.get(), item.getPath());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
((BackPressedHandler.HostActivity) getActivity())
|
||||
.getBackPressedObserver()
|
||||
.registerHandlerAtFront(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
((BackPressedHandler.HostActivity) getActivity())
|
||||
.getBackPressedObserver()
|
||||
.unregisterHandler(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFabClick(FloatingActionButton fab) {
|
||||
initFloatingActionMenuIfNeeded(fab);
|
||||
@@ -98,7 +85,7 @@ public class MyScriptListFragment extends ViewPagerFragment implements BackPress
|
||||
private void initFloatingActionMenuIfNeeded(final FloatingActionButton fab) {
|
||||
if (mFloatingActionMenu != null)
|
||||
return;
|
||||
mFloatingActionMenu = ((FloatingActionMenu) getActivity().findViewById(R.id.floating_action_menu));
|
||||
mFloatingActionMenu = getActivity().findViewById(R.id.floating_action_menu);
|
||||
mFloatingActionMenu.getState()
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new SimpleObserver<Boolean>() {
|
||||
|
||||
@@ -1,24 +1,33 @@
|
||||
package org.autojs.autojs.ui.main.task;
|
||||
|
||||
import android.content.Intent;
|
||||
|
||||
import com.stardust.app.GlobalAppContext;
|
||||
import com.stardust.autojs.engine.ScriptEngine;
|
||||
import com.stardust.autojs.execution.ScriptExecution;
|
||||
import com.stardust.autojs.script.AutoFileSource;
|
||||
import com.stardust.autojs.script.JavaScriptSource;
|
||||
import com.stardust.pio.PFiles;
|
||||
import com.stardust.util.MapBuilder;
|
||||
|
||||
import org.autojs.autojs.R;
|
||||
import org.autojs.autojs.timing.IntentTask;
|
||||
import org.autojs.autojs.timing.TimedTask;
|
||||
import org.autojs.autojs.timing.TimedTaskManager;
|
||||
|
||||
import org.joda.time.format.DateTimeFormat;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static org.autojs.autojs.ui.timing.TimedTaskSettingActivity.ACTION_DESC_MAP;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/11/28.
|
||||
*/
|
||||
|
||||
public abstract class Task {
|
||||
|
||||
|
||||
public abstract String getName();
|
||||
|
||||
public abstract String getDesc();
|
||||
@@ -29,11 +38,26 @@ public abstract class Task {
|
||||
|
||||
public static class PendingTask extends Task {
|
||||
|
||||
|
||||
private TimedTask mTimedTask;
|
||||
private IntentTask mIntentTask;
|
||||
|
||||
|
||||
public PendingTask(TimedTask timedTask) {
|
||||
mTimedTask = timedTask;
|
||||
mIntentTask = null;
|
||||
}
|
||||
|
||||
public PendingTask(IntentTask intentTask) {
|
||||
mIntentTask = intentTask;
|
||||
mTimedTask = null;
|
||||
}
|
||||
|
||||
public boolean taskEquals(Object task) {
|
||||
if (mTimedTask != null) {
|
||||
return mTimedTask.equals(task);
|
||||
}
|
||||
return mIntentTask.equals(task);
|
||||
}
|
||||
|
||||
public TimedTask getTimedTask() {
|
||||
@@ -42,24 +66,47 @@ public abstract class Task {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return PFiles.getSimplifiedPath(mTimedTask.getScriptPath());
|
||||
return PFiles.getSimplifiedPath(getScriptPath());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDesc() {
|
||||
long nextTime = mTimedTask.getNextTime();
|
||||
return GlobalAppContext.getString(R.string.text_next_run_time) + ": " +
|
||||
DateTimeFormat.shortDateTime().print(nextTime);
|
||||
if (mTimedTask != null) {
|
||||
long nextTime = mTimedTask.getNextTime();
|
||||
return GlobalAppContext.getString(R.string.text_next_run_time) + ": " +
|
||||
DateTimeFormat.shortDateTime().print(nextTime);
|
||||
} else {
|
||||
assert mIntentTask != null;
|
||||
Integer desc = ACTION_DESC_MAP.get(mIntentTask.getAction());
|
||||
if(desc != null){
|
||||
return GlobalAppContext.getString(desc);
|
||||
}
|
||||
return mIntentTask.getAction();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
TimedTaskManager.getInstance().removeTask(mTimedTask);
|
||||
if (mTimedTask != null) {
|
||||
TimedTaskManager.getInstance().removeTask(mTimedTask);
|
||||
} else {
|
||||
TimedTaskManager.getInstance().removeTask(mIntentTask);
|
||||
}
|
||||
}
|
||||
|
||||
private String getScriptPath() {
|
||||
if (mTimedTask != null) {
|
||||
return mTimedTask.getScriptPath();
|
||||
} else {
|
||||
assert mIntentTask != null;
|
||||
return mIntentTask.getScriptPath();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEngineName() {
|
||||
if (mTimedTask.getScriptPath().endsWith(".js")) {
|
||||
if (getScriptPath().endsWith(".js")) {
|
||||
return JavaScriptSource.ENGINE;
|
||||
} else {
|
||||
return AutoFileSource.ENGINE;
|
||||
@@ -69,6 +116,16 @@ public abstract class Task {
|
||||
public void setTimedTask(TimedTask timedTask) {
|
||||
mTimedTask = timedTask;
|
||||
}
|
||||
|
||||
public void setIntentTask(IntentTask intentTask) {
|
||||
mIntentTask = intentTask;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
if(mTimedTask != null)
|
||||
return mTimedTask.getId();
|
||||
return mIntentTask.getId();
|
||||
}
|
||||
}
|
||||
|
||||
public static class RunningTask extends Task {
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.stardust.autojs.execution.ScriptExecution;
|
||||
|
||||
import org.autojs.autojs.R;
|
||||
import org.autojs.autojs.autojs.AutoJs;
|
||||
import org.autojs.autojs.timing.IntentTask;
|
||||
import org.autojs.autojs.timing.TimedTask;
|
||||
import org.autojs.autojs.timing.TimedTaskManager;
|
||||
|
||||
@@ -55,39 +56,56 @@ public abstract class TaskGroup implements Parent<Task> {
|
||||
|
||||
@Override
|
||||
public void refresh() {
|
||||
List<TimedTask> timedTasks = TimedTaskManager.getInstance().getAllTasksAsList();
|
||||
mTasks.clear();
|
||||
for (TimedTask timedTask : timedTasks) {
|
||||
for (TimedTask timedTask : TimedTaskManager.getInstance().getAllTasksAsList()) {
|
||||
mTasks.add(new Task.PendingTask(timedTask));
|
||||
}
|
||||
for (IntentTask intentTask : TimedTaskManager.getInstance().getAllIntentTasksAsList()) {
|
||||
mTasks.add(new Task.PendingTask(intentTask));
|
||||
}
|
||||
}
|
||||
|
||||
public int addTask(TimedTask timedTask) {
|
||||
public int addTask(Object task) {
|
||||
int pos = mTasks.size();
|
||||
mTasks.add(new Task.PendingTask(timedTask));
|
||||
if (task instanceof TimedTask) {
|
||||
mTasks.add(new Task.PendingTask((TimedTask) task));
|
||||
} else if (task instanceof IntentTask) {
|
||||
mTasks.add(new Task.PendingTask((IntentTask) task));
|
||||
} else {
|
||||
throw new IllegalArgumentException("task = " + task);
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
public int removeTask(TimedTask data) {
|
||||
public int removeTask(Object data) {
|
||||
int i = indexOf(data);
|
||||
if (i >= 0)
|
||||
mTasks.remove(i);
|
||||
return i;
|
||||
}
|
||||
|
||||
private int indexOf(TimedTask data) {
|
||||
private int indexOf(Object data) {
|
||||
for (int i = 0; i < mTasks.size(); i++) {
|
||||
if (((Task.PendingTask) mTasks.get(i)).getTimedTask().equals(data)) {
|
||||
Task.PendingTask task = (Task.PendingTask) mTasks.get(i);
|
||||
if (task.taskEquals(data)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int updateTask(TimedTask task) {
|
||||
|
||||
public int updateTask(Object task) {
|
||||
int i = indexOf(task);
|
||||
if (i >= 0)
|
||||
((Task.PendingTask) mTasks.get(i)).setTimedTask(task);
|
||||
if (i >= 0) {
|
||||
if (task instanceof TimedTask) {
|
||||
((Task.PendingTask) mTasks.get(i)).setTimedTask((TimedTask) task);
|
||||
} else if (task instanceof IntentTask) {
|
||||
((Task.PendingTask) mTasks.get(i)).setIntentTask((IntentTask) task);
|
||||
} else {
|
||||
throw new IllegalArgumentException("task = " + task);
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,30 +13,28 @@ import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.stardust.autojs.workground.WrapContentLinearLayoutManager;
|
||||
|
||||
import com.bignerdranch.expandablerecyclerview.ChildViewHolder;
|
||||
import com.bignerdranch.expandablerecyclerview.ExpandableRecyclerAdapter;
|
||||
import com.bignerdranch.expandablerecyclerview.ParentViewHolder;
|
||||
import com.raizlabs.android.dbflow.structure.BaseModel;
|
||||
import com.stardust.autojs.ScriptEngineService;
|
||||
import com.stardust.autojs.engine.ScriptEngineManager;
|
||||
import com.stardust.autojs.execution.ScriptExecution;
|
||||
import com.stardust.autojs.execution.ScriptExecutionListener;
|
||||
import com.stardust.autojs.execution.SimpleScriptExecutionListener;
|
||||
import com.stardust.autojs.engine.ScriptEngine;
|
||||
import com.stardust.autojs.script.AutoFileSource;
|
||||
import com.stardust.autojs.workground.WrapContentLinearLayoutManager;
|
||||
import com.yqritc.recyclerviewflexibledivider.HorizontalDividerItemDecoration;
|
||||
|
||||
import org.autojs.autojs.R;
|
||||
import org.autojs.autojs.autojs.AutoJs;
|
||||
import org.autojs.autojs.external.tasker.TaskerScriptEditActivity;
|
||||
import org.autojs.autojs.storage.database.ModelChange;
|
||||
import org.autojs.autojs.timing.IntentTask;
|
||||
import org.autojs.autojs.timing.TaskReceiver;
|
||||
import org.autojs.autojs.timing.TimedTask;
|
||||
import org.autojs.autojs.timing.TimedTaskManager;
|
||||
import org.autojs.autojs.ui.timing.TimedTaskSettingActivity;
|
||||
import org.autojs.autojs.ui.timing.TimedTaskSettingActivity_;
|
||||
|
||||
import com.yqritc.recyclerviewflexibledivider.HorizontalDividerItemDecoration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -60,7 +58,7 @@ public class TaskListRecyclerView extends ThemeColorRecyclerView {
|
||||
private TaskGroup.PendingTaskGroup mPendingTaskGroup;
|
||||
private Adapter mAdapter;
|
||||
private Disposable mTimedTaskChangeDisposable;
|
||||
private final ScriptEngineService mScriptEngineService = AutoJs.getInstance().getScriptEngineService();
|
||||
private Disposable mIntentTaskChangeDisposable;
|
||||
private ScriptExecutionListener mScriptExecutionListener = new SimpleScriptExecutionListener() {
|
||||
@Override
|
||||
public void onStart(final ScriptExecution execution) {
|
||||
@@ -135,7 +133,10 @@ public class TaskListRecyclerView extends ThemeColorRecyclerView {
|
||||
AutoJs.getInstance().getScriptEngineService().registerGlobalScriptExecutionListener(mScriptExecutionListener);
|
||||
mTimedTaskChangeDisposable = TimedTaskManager.getInstance().getTimeTaskChanges()
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(this::onTimedTaskChange);
|
||||
.subscribe(this::onTaskChange);
|
||||
mIntentTaskChangeDisposable = TimedTaskManager.getInstance().getIntentTaskChanges()
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(this::onTaskChange);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -151,26 +152,25 @@ public class TaskListRecyclerView extends ThemeColorRecyclerView {
|
||||
super.onDetachedFromWindow();
|
||||
AutoJs.getInstance().getScriptEngineService().unregisterGlobalScriptExecutionListener(mScriptExecutionListener);
|
||||
mTimedTaskChangeDisposable.dispose();
|
||||
mIntentTaskChangeDisposable.dispose();
|
||||
}
|
||||
|
||||
void onTimedTaskChange(ModelChange<TimedTask> taskChange) {
|
||||
if (taskChange.getAction() == BaseModel.Action.INSERT) {
|
||||
void onTaskChange(ModelChange taskChange) {
|
||||
if (taskChange.getAction() == ModelChange.INSERT) {
|
||||
mAdapter.notifyChildInserted(1, mPendingTaskGroup.addTask(taskChange.getData()));
|
||||
} else if (taskChange.getAction() == BaseModel.Action.DELETE) {
|
||||
} else if (taskChange.getAction() == ModelChange.DELETE) {
|
||||
final int i = mPendingTaskGroup.removeTask(taskChange.getData());
|
||||
// FIXME: 2017/11/28 task id is always 0
|
||||
if (i >= 0) {
|
||||
mAdapter.notifyChildRemoved(1, i);
|
||||
} else {
|
||||
Log.w(LOG_TAG, "data inconsistent on change: " + taskChange);
|
||||
refresh();
|
||||
}
|
||||
} else if (taskChange.getAction() == BaseModel.Action.UPDATE) {
|
||||
} else if (taskChange.getAction() == ModelChange.UPDATE) {
|
||||
final int i = mPendingTaskGroup.updateTask(taskChange.getData());
|
||||
if (i >= 0) {
|
||||
mAdapter.notifyChildChanged(1, i);
|
||||
} else {
|
||||
Log.w(LOG_TAG, "data inconsistent on change: " + taskChange);
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
@@ -249,8 +249,11 @@ public class TaskListRecyclerView extends ThemeColorRecyclerView {
|
||||
|
||||
void onItemClick(View view) {
|
||||
if (mTask instanceof Task.PendingTask) {
|
||||
Task.PendingTask task = (Task.PendingTask) mTask;
|
||||
String extra = task.getTimedTask() == null ? TimedTaskSettingActivity.EXTRA_INTENT_TASK_ID
|
||||
: TimedTaskSettingActivity.EXTRA_TASK_ID;
|
||||
TimedTaskSettingActivity_.intent(getContext())
|
||||
.extra(TaskReceiver.EXTRA_TASK_ID, ((Task.PendingTask) mTask).getTimedTask().getId())
|
||||
.extra(extra, task.getId())
|
||||
.start();
|
||||
}
|
||||
}
|
||||
@@ -263,8 +266,8 @@ public class TaskListRecyclerView extends ThemeColorRecyclerView {
|
||||
|
||||
TaskGroupViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
title = (TextView) itemView.findViewById(R.id.title);
|
||||
icon = (ImageView) itemView.findViewById(R.id.icon);
|
||||
title = itemView.findViewById(R.id.title);
|
||||
icon = itemView.findViewById(R.id.icon);
|
||||
itemView.setOnClickListener(view -> {
|
||||
if (isExpanded()) {
|
||||
collapseView();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.autojs.autojs.ui.main.task;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.support.v4.widget.SwipeRefreshLayout;
|
||||
@@ -70,4 +71,8 @@ public class TaskManagerFragment extends ViewPagerFragment {
|
||||
AutoJs.getInstance().getScriptEngineService().stopAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onBackPressed(Activity activity) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ import org.autojs.autojs.ui.shortcut.ShortcutIconSelectActivity_;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.security.KeyStore;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
@@ -116,7 +117,6 @@ public class BuildActivity extends BaseActivity implements AutoJsApkBuilder.Prog
|
||||
if (version < ApkBuilderPluginHelper.getSuitablePluginVersion()) {
|
||||
showPluginDownloadDialog(R.string.apk_builder_plugin_version_too_low, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void showPluginDownloadDialog(int msgRes, boolean finishIfCanceled) {
|
||||
|
||||
@@ -12,6 +12,7 @@ import android.widget.ImageView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.stardust.autojs.project.ProjectConfig;
|
||||
import com.stardust.autojs.runtime.api.Dialogs;
|
||||
import com.stardust.pio.PFiles;
|
||||
|
||||
import org.androidannotations.annotations.AfterViews;
|
||||
@@ -24,6 +25,7 @@ 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.model.project.ProjectTemplate;
|
||||
import org.autojs.autojs.theme.dialog.ThemeColorMaterialDialogBuilder;
|
||||
import org.autojs.autojs.ui.BaseActivity;
|
||||
import org.autojs.autojs.ui.widget.SimpleTextWatcher;
|
||||
|
||||
@@ -89,11 +91,21 @@ public class ProjectConfigActivity extends BaseActivity {
|
||||
}
|
||||
mDirectory = new File(dir);
|
||||
mProjectConfig = ProjectConfig.fromProjectDir(dir);
|
||||
if (mProjectConfig == null) {
|
||||
new ThemeColorMaterialDialogBuilder(this)
|
||||
.title(R.string.text_invalid_project)
|
||||
.positiveText(R.string.ok)
|
||||
.dismissListener(dialogInterface -> finish())
|
||||
.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@AfterViews
|
||||
void setupViews() {
|
||||
if (mProjectConfig == null) {
|
||||
return;
|
||||
}
|
||||
setToolbarAsBack(mNewProject ? getString(R.string.text_new_project) : mProjectConfig.getName());
|
||||
if (mNewProject) {
|
||||
mAppName.addTextChangedListener(new SimpleTextWatcher(s ->
|
||||
|
||||
@@ -12,7 +12,7 @@ import android.view.View;
|
||||
import com.stardust.theme.app.ColorSelectActivity;
|
||||
import com.stardust.theme.preference.ThemeColorPreferenceFragment;
|
||||
import com.stardust.theme.util.ListBuilder;
|
||||
import com.stardust.util.MapEntries;
|
||||
import com.stardust.util.MapBuilder;
|
||||
|
||||
import org.androidannotations.annotations.AfterViews;
|
||||
import org.androidannotations.annotations.EActivity;
|
||||
@@ -100,14 +100,14 @@ public class SettingsActivity extends BaseActivity {
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
ACTION_MAP = new MapEntries<String, Runnable>()
|
||||
.entry(getString(R.string.text_theme_color), () -> selectThemeColor(getActivity()))
|
||||
.entry(getString(R.string.text_check_for_updates), () -> new UpdateCheckDialog(getActivity())
|
||||
ACTION_MAP = new MapBuilder<String, Runnable>()
|
||||
.put(getString(R.string.text_theme_color), () -> selectThemeColor(getActivity()))
|
||||
.put(getString(R.string.text_check_for_updates), () -> new UpdateCheckDialog(getActivity())
|
||||
.show())
|
||||
.entry(getString(R.string.text_issue_report), () -> startActivity(new Intent(getActivity(), IssueReporterActivity.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)))
|
||||
.entry(getString(R.string.text_about_me_and_repo), () -> startActivity(new Intent(getActivity(), AboutActivity_.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)))
|
||||
.entry(getString(R.string.text_licenses), () -> showLicenseDialog())
|
||||
.map();
|
||||
.put(getString(R.string.text_issue_report), () -> startActivity(new Intent(getActivity(), IssueReporterActivity.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)))
|
||||
.put(getString(R.string.text_about_me_and_repo), () -> startActivity(new Intent(getActivity(), AboutActivity_.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)))
|
||||
.put(getString(R.string.text_licenses), () -> showLicenseDialog())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -51,7 +51,7 @@ public class SplashActivity extends BaseActivity {
|
||||
mNotStartMainActivity = getIntent().getBooleanExtra(NOT_START_MAIN_ACTIVITY, false);
|
||||
boolean forceShowAd = getIntent().getBooleanExtra(FORCE_SHOW_AD, false);
|
||||
setContentView(R.layout.activity_splash);
|
||||
mFullScreenAdView = (FullScreenAdView) findViewById(R.id.full_screen_view);
|
||||
mFullScreenAdView = findViewById(R.id.full_screen_view);
|
||||
if (!forceShowAd && !Pref.shouldShowAd()) {
|
||||
mFullScreenAdView.setVisibility(View.INVISIBLE);
|
||||
mHandler.postDelayed(this::enterNextActivity, 1500);
|
||||
|
||||
@@ -3,6 +3,8 @@ package org.autojs.autojs.ui.timing;
|
||||
import android.app.DatePickerDialog;
|
||||
import android.app.TimePickerDialog;
|
||||
import android.content.Intent;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
@@ -18,6 +20,7 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RadioButton;
|
||||
import android.widget.RadioGroup;
|
||||
@@ -27,6 +30,9 @@ import android.widget.Toast;
|
||||
|
||||
import com.github.aakira.expandablelayout.ExpandableRelativeLayout;
|
||||
import com.stardust.autojs.execution.ExecutionConfig;
|
||||
import com.stardust.util.BiMap;
|
||||
import com.stardust.util.BiMaps;
|
||||
import com.stardust.util.MapBuilder;
|
||||
|
||||
import org.androidannotations.annotations.AfterViews;
|
||||
import org.androidannotations.annotations.CheckedChange;
|
||||
@@ -49,6 +55,7 @@ import org.joda.time.format.DateTimeFormatter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/11/28.
|
||||
@@ -56,12 +63,51 @@ import java.util.List;
|
||||
@EActivity(R.layout.activity_timed_task_setting)
|
||||
public class TimedTaskSettingActivity extends BaseActivity {
|
||||
|
||||
public static final String EXTRA_INTENT_TASK_ID = "intent_task_id";
|
||||
public static final String EXTRA_TASK_ID = TaskReceiver.EXTRA_TASK_ID;
|
||||
|
||||
private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormat.forPattern("HH:mm");
|
||||
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormat.forPattern("yy-MM-dd");
|
||||
private static final int REQUEST_CODE_IGNORE_BATTERY = 27101;
|
||||
|
||||
private static final String LOG_TAG = "TimedTaskSettings";
|
||||
|
||||
|
||||
public static final Map<String, Integer> ACTION_DESC_MAP = new MapBuilder<String, Integer>()
|
||||
.put(Intent.ACTION_BOOT_COMPLETED, R.string.text_run_on_boot)
|
||||
.put(Intent.ACTION_SCREEN_OFF, R.string.text_run_on_screen_off)
|
||||
.put(Intent.ACTION_SCREEN_ON, R.string.text_run_on_screen_on)
|
||||
.put(Intent.ACTION_USER_PRESENT, R.string.text_run_on_screen_unlock)
|
||||
.put(Intent.ACTION_BATTERY_CHANGED, R.string.text_run_on_battery_change)
|
||||
.put(Intent.ACTION_POWER_CONNECTED, R.string.text_run_on_power_connect)
|
||||
.put(Intent.ACTION_POWER_DISCONNECTED, R.string.text_run_on_power_disconnect)
|
||||
.put(ConnectivityManager.CONNECTIVITY_ACTION, R.string.text_run_on_conn_change)
|
||||
.put(Intent.ACTION_PACKAGE_ADDED, R.string.text_run_on_package_install)
|
||||
.put(Intent.ACTION_PACKAGE_REMOVED, R.string.text_run_on_package_uninstall)
|
||||
.put(Intent.ACTION_PACKAGE_REPLACED, R.string.text_run_on_package_update)
|
||||
.put(Intent.ACTION_HEADSET_PLUG, R.string.text_run_on_headset_plug)
|
||||
.put(Intent.ACTION_CONFIGURATION_CHANGED, R.string.text_run_on_config_change)
|
||||
.put(Intent.ACTION_TIME_TICK, R.string.text_run_on_time_tick)
|
||||
.build();
|
||||
|
||||
private static final BiMap<Integer, String> ACTIONS = BiMaps.<Integer, String>newBuilder()
|
||||
.put(R.id.run_on_boot, Intent.ACTION_BOOT_COMPLETED)
|
||||
.put(R.id.run_on_screen_off, Intent.ACTION_SCREEN_OFF)
|
||||
.put(R.id.run_on_screen_on, Intent.ACTION_SCREEN_ON)
|
||||
.put(R.id.run_on_screen_unlock, Intent.ACTION_USER_PRESENT)
|
||||
.put(R.id.run_on_battery_change, Intent.ACTION_BATTERY_CHANGED)
|
||||
.put(R.id.run_on_power_connect, Intent.ACTION_POWER_CONNECTED)
|
||||
.put(R.id.run_on_power_disconnect, Intent.ACTION_POWER_DISCONNECTED)
|
||||
.put(R.id.run_on_conn_change, ConnectivityManager.CONNECTIVITY_ACTION)
|
||||
.put(R.id.run_on_package_install, Intent.ACTION_PACKAGE_ADDED)
|
||||
.put(R.id.run_on_package_uninstall, Intent.ACTION_PACKAGE_REMOVED)
|
||||
.put(R.id.run_on_package_update, Intent.ACTION_PACKAGE_REPLACED)
|
||||
.put(R.id.run_on_headset_plug, Intent.ACTION_HEADSET_PLUG)
|
||||
.put(R.id.run_on_config_change, Intent.ACTION_CONFIGURATION_CHANGED)
|
||||
.put(R.id.run_on_time_tick, Intent.ACTION_TIME_TICK)
|
||||
.build();
|
||||
|
||||
|
||||
@ViewById(R.id.toolbar)
|
||||
Toolbar mToolbar;
|
||||
|
||||
@@ -77,9 +123,17 @@ public class TimedTaskSettingActivity extends BaseActivity {
|
||||
@ViewById(R.id.weekly_task_radio)
|
||||
RadioButton mWeeklyTaskRadio;
|
||||
|
||||
@ViewById(R.id.run_on_boot_radio)
|
||||
RadioButton mRunOnBootRadio;
|
||||
@ViewById(R.id.run_on_broadcast)
|
||||
RadioButton mRunOnBroadcastRadio;
|
||||
|
||||
@ViewById(R.id.run_on_other_broadcast)
|
||||
RadioButton mRunOnOtherBroadcast;
|
||||
|
||||
@ViewById(R.id.action)
|
||||
EditText mOtherBroadcastAction;
|
||||
|
||||
@ViewById(R.id.broadcast_group)
|
||||
RadioGroup mBroadcastGroup;
|
||||
|
||||
@ViewById(R.id.disposable_task_time)
|
||||
TextView mDisposableTaskTime;
|
||||
@@ -98,25 +152,33 @@ public class TimedTaskSettingActivity extends BaseActivity {
|
||||
|
||||
private List<CheckBox> mDayOfWeekCheckBoxes = new ArrayList<>();
|
||||
|
||||
|
||||
private ScriptFile mScriptFile;
|
||||
private TimedTask mTimedTask;
|
||||
private IntentTask mIntentTask;
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
int taskId = getIntent().getIntExtra(TaskReceiver.EXTRA_TASK_ID, -1);
|
||||
long taskId = getIntent().getLongExtra(EXTRA_TASK_ID, -1);
|
||||
if (taskId != -1) {
|
||||
mTimedTask = TimedTaskManager.getInstance().getTimedTask(taskId);
|
||||
if (mTimedTask != null) {
|
||||
mScriptFile = new ScriptFile(mTimedTask.getScriptPath());
|
||||
}
|
||||
} else {
|
||||
String path = getIntent().getStringExtra(ScriptIntents.EXTRA_KEY_PATH);
|
||||
if (TextUtils.isEmpty(path)) {
|
||||
finish();
|
||||
long intentTaskId = getIntent().getLongExtra(EXTRA_INTENT_TASK_ID, -1);
|
||||
if (intentTaskId != -1) {
|
||||
mIntentTask = TimedTaskManager.getInstance().getIntentTask(intentTaskId);
|
||||
if (mIntentTask != null) {
|
||||
mScriptFile = new ScriptFile(mIntentTask.getScriptPath());
|
||||
}
|
||||
} else {
|
||||
String path = getIntent().getStringExtra(ScriptIntents.EXTRA_KEY_PATH);
|
||||
if (TextUtils.isEmpty(path)) {
|
||||
finish();
|
||||
}
|
||||
mScriptFile = new ScriptFile(path);
|
||||
}
|
||||
mScriptFile = new ScriptFile(path);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -128,7 +190,7 @@ public class TimedTaskSettingActivity extends BaseActivity {
|
||||
mToolbar.setSubtitle(mScriptFile.getName());
|
||||
}
|
||||
findDayOfWeekCheckBoxes(mWeeklyTaskContainer);
|
||||
setUpTime();
|
||||
setUpTaskSettings();
|
||||
}
|
||||
|
||||
private void findDayOfWeekCheckBoxes(ViewGroup parent) {
|
||||
@@ -145,13 +207,32 @@ public class TimedTaskSettingActivity extends BaseActivity {
|
||||
|
||||
}
|
||||
|
||||
private void setUpTime() {
|
||||
private void setUpTaskSettings() {
|
||||
mDisposableTaskDate.setText(DATE_FORMATTER.print(LocalDate.now()));
|
||||
mDisposableTaskTime.setText(TIME_FORMATTER.print(LocalTime.now()));
|
||||
if (mTimedTask == null) {
|
||||
mDailyTaskRadio.setChecked(true);
|
||||
if (mTimedTask != null) {
|
||||
setupTime();
|
||||
return;
|
||||
}
|
||||
if (mIntentTask != null) {
|
||||
setupAction();
|
||||
return;
|
||||
}
|
||||
mDailyTaskRadio.setChecked(true);
|
||||
}
|
||||
|
||||
private void setupAction() {
|
||||
mRunOnBroadcastRadio.setChecked(true);
|
||||
Integer buttonId = ACTIONS.getKey(mIntentTask.getAction());
|
||||
if (buttonId == null) {
|
||||
mRunOnOtherBroadcast.setChecked(true);
|
||||
mOtherBroadcastAction.setText(mIntentTask.getAction());
|
||||
} else {
|
||||
((RadioButton) findViewById(buttonId)).setChecked(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void setupTime() {
|
||||
if (mTimedTask.isDisposable()) {
|
||||
mDisposableTaskRadio.setChecked(true);
|
||||
mDisposableTaskTime.setText(TIME_FORMATTER.print(mTimedTask.getMillis()));
|
||||
@@ -171,11 +252,10 @@ public class TimedTaskSettingActivity extends BaseActivity {
|
||||
mDayOfWeekCheckBoxes.get(i).setChecked(mTimedTask.hasDayOfWeek(i + 1));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@CheckedChange({R.id.daily_task_radio, R.id.weekly_task_radio, R.id.disposable_task_radio})
|
||||
@CheckedChange({R.id.daily_task_radio, R.id.weekly_task_radio, R.id.disposable_task_radio, R.id.run_on_broadcast})
|
||||
void onCheckedChanged(CompoundButton button) {
|
||||
ExpandableRelativeLayout relativeLayout = findExpandableLayoutOf(button);
|
||||
if (button.isChecked()) {
|
||||
@@ -269,10 +349,8 @@ public class TimedTaskSettingActivity extends BaseActivity {
|
||||
startActivityForResult(new Intent().setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)
|
||||
.setData(Uri.parse("package:" + getPackageName())), REQUEST_CODE_IGNORE_BATTERY);
|
||||
} else {
|
||||
createOrUpdateTimedTask();
|
||||
createOrUpdateTask();
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
@@ -282,18 +360,14 @@ public class TimedTaskSettingActivity extends BaseActivity {
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (requestCode == REQUEST_CODE_IGNORE_BATTERY) {
|
||||
Log.d(LOG_TAG, "result code = " + requestCode);
|
||||
createOrUpdateTimedTask();
|
||||
createOrUpdateTask();
|
||||
}
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
private void createOrUpdateTimedTask() {
|
||||
if (mRunOnBootRadio.isChecked()) {
|
||||
IntentTask task = new IntentTask();
|
||||
task.setAction(Intent.ACTION_BOOT_COMPLETED);
|
||||
task.setScriptPath(mScriptFile.getPath());
|
||||
TimedTaskManager.getInstance().addTask(task);
|
||||
finish();
|
||||
private void createOrUpdateTask() {
|
||||
if (mRunOnBroadcastRadio.isChecked()) {
|
||||
createOrUpdateIntentTask();
|
||||
return;
|
||||
}
|
||||
TimedTask task = createTimedTask();
|
||||
@@ -301,6 +375,9 @@ public class TimedTaskSettingActivity extends BaseActivity {
|
||||
return;
|
||||
if (mTimedTask == null) {
|
||||
TimedTaskManager.getInstance().addTask(task);
|
||||
if (mIntentTask != null) {
|
||||
TimedTaskManager.getInstance().removeTask(mIntentTask);
|
||||
}
|
||||
Toast.makeText(this, R.string.text_already_create, Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
task.setId(mTimedTask.getId());
|
||||
@@ -308,4 +385,38 @@ public class TimedTaskSettingActivity extends BaseActivity {
|
||||
}
|
||||
finish();
|
||||
}
|
||||
|
||||
|
||||
private void createOrUpdateIntentTask() {
|
||||
int buttonId = mBroadcastGroup.getCheckedRadioButtonId();
|
||||
if (buttonId == -1) {
|
||||
Toast.makeText(this, R.string.error_empty_selection, Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
String action;
|
||||
if (buttonId == R.id.run_on_other_broadcast) {
|
||||
action = mOtherBroadcastAction.getText().toString();
|
||||
if (action.isEmpty()) {
|
||||
mOtherBroadcastAction.setError(getString(R.string.text_should_not_be_empty));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
action = ACTIONS.get(buttonId);
|
||||
}
|
||||
IntentTask task = new IntentTask();
|
||||
task.setAction(action);
|
||||
task.setScriptPath(mScriptFile.getPath());
|
||||
if (mIntentTask != null) {
|
||||
task.setId(mIntentTask.getId());
|
||||
TimedTaskManager.getInstance().updateTask(task);
|
||||
Toast.makeText(this, R.string.text_already_create, Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
TimedTaskManager.getInstance().addTask(task);
|
||||
if (mTimedTask != null) {
|
||||
TimedTaskManager.getInstance().removeTask(mTimedTask);
|
||||
}
|
||||
}
|
||||
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ public class BubblePopupMenu extends PopupWindow {
|
||||
} else {
|
||||
params.leftMargin = 0;
|
||||
}
|
||||
if (y + height > screenHeight) {
|
||||
if (y > screenHeight / 2) {
|
||||
getContentView().setRotation(180);
|
||||
mRecyclerView.setRotation(180);
|
||||
params.leftMargin = -params.leftMargin;
|
||||
|
||||
Reference in New Issue
Block a user