diff --git a/.idea/misc.xml b/.idea/misc.xml index efe3417d..13edfcd8 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -2,7 +2,7 @@ - + @@ -11,7 +11,8 @@ - + + diff --git a/app/build.gradle b/app/build.gradle index 1ef20527..ea8d5991 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -9,8 +9,8 @@ android { applicationId "com.stardust.scriptdroid" minSdkVersion 17 targetSdkVersion 23 - versionCode 163 - versionName "2.0.16 Beta2.1" + versionCode 200 + versionName "3.0.0 Alpha1" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" multiDexEnabled true ndk { @@ -124,12 +124,16 @@ dependencies { compile 'com.bignerdranch.android:expandablerecyclerview:3.0.0-RC1' compile 'com.yqritc:recyclerview-flexibledivider:1.4.0' compile 'com.wang.avi:library:2.1.3' + // RxJava compile "io.reactivex.rxjava2:rxjava:2.1.0" compile 'io.reactivex.rxjava2:rxandroid:2.0.1' - + // Retrofit + compile 'com.squareup.retrofit2:retrofit:2.3.0' + compile 'com.squareup.retrofit2:converter-gson:2.3.0' + compile 'com.squareup.retrofit2:converter-gson:2.3.0' + compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0' // Tasker Plugin compile 'com.twofortyfouram:android-plugin-client-sdk-for-locale:[4.0.2, 5.0[' - compile 'com.android.volley:volley:1.0.0' compile 'com.flurry.android:analytics:7.0.0@aar' compile 'com.pushtorefresh.storio:sqlite:1.12.3' // 920 Text Editors diff --git a/app/src/main/java/com/stardust/scriptdroid/network/Apis.java b/app/src/main/java/com/stardust/scriptdroid/network/Apis.java new file mode 100644 index 00000000..7a76849d --- /dev/null +++ b/app/src/main/java/com/stardust/scriptdroid/network/Apis.java @@ -0,0 +1,8 @@ +package com.stardust.scriptdroid.network; + +/** + * Created by Stardust on 2017/9/20. + */ + +public class Apis { +} diff --git a/app/src/main/java/com/stardust/scriptdroid/network/UpdateCheckApi.java b/app/src/main/java/com/stardust/scriptdroid/network/UpdateCheckApi.java new file mode 100644 index 00000000..1777df63 --- /dev/null +++ b/app/src/main/java/com/stardust/scriptdroid/network/UpdateCheckApi.java @@ -0,0 +1,17 @@ +package com.stardust.scriptdroid.network; + +import com.stardust.scriptdroid.network.entity.VersionInfo; + +import io.reactivex.Observable; +import retrofit2.http.GET; + +/** + * Created by Stardust on 2017/9/20. + */ + +public interface UpdateCheckApi { + + @GET("/hyb1996/NoRootScriptDroid/master/version.json") + Observable checkForUpdates(); + +} diff --git a/app/src/main/java/com/stardust/scriptdroid/network/VersionService.java b/app/src/main/java/com/stardust/scriptdroid/network/VersionService.java new file mode 100644 index 00000000..0aa300d3 --- /dev/null +++ b/app/src/main/java/com/stardust/scriptdroid/network/VersionService.java @@ -0,0 +1,150 @@ +package com.stardust.scriptdroid.network; + +import android.content.Context; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; +import android.widget.Toast; + +import com.google.gson.GsonBuilder; +import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; +import com.stardust.scriptdroid.App; +import com.stardust.scriptdroid.BuildConfig; +import com.stardust.scriptdroid.R; +import com.stardust.scriptdroid.network.entity.VersionInfo; +import com.stardust.scriptdroid.tool.SimpleObserver; +import com.stardust.scriptdroid.ui.update.UpdateInfoDialogBuilder; +import com.stardust.util.NetworkUtils; + +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.annotations.NonNull; +import io.reactivex.schedulers.Schedulers; +import retrofit2.Retrofit; +import retrofit2.converter.gson.GsonConverterFactory; + +/** + * Created by Stardust on 2017/9/20. + */ + +public class VersionService { + + private static final String KEY_DEPRECATED = "Still loving you...Can we go back..."; + private static final String KEY_DEPRECATED_VERSION_CODE = "I miss you so much tonight...Baby don't let me cry..."; + + private static VersionService sInstance = new VersionService(); + private boolean mDeprecated = false; + private VersionInfo mVersionInfo; + private SharedPreferences mSharedPreferences; + private Retrofit mRetrofit; + + public VersionService() { + mRetrofit = new Retrofit.Builder() + .baseUrl("https://raw.githubusercontent.com/") + .addConverterFactory(GsonConverterFactory.create(new GsonBuilder() + .setLenient() + .create())) + .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) + .build(); + } + + public static VersionService getInstance() { + return sInstance; + } + + public Observable checkForUpdates() { + return mRetrofit.create(UpdateCheckApi.class) + .checkForUpdates() + .subscribeOn(Schedulers.io()); + } + + public void checkForUpdatesAndShow(final Context context) { + checkForUpdates().observeOn(AndroidSchedulers.mainThread()) + .subscribe(new SimpleObserver() { + + @Override + public void onNext(@io.reactivex.annotations.NonNull VersionInfo versionInfo) { + new UpdateInfoDialogBuilder(context, versionInfo) + .show(); + } + + @Override + public void onError(@io.reactivex.annotations.NonNull Throwable e) { + Toast.makeText(App.getApp(), R.string.text_check_update_error, Toast.LENGTH_SHORT).show(); + } + }); + } + + + private void readDeprecatedFromPref(Context context) { + mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(context); + if (mSharedPreferences.getInt(KEY_DEPRECATED_VERSION_CODE, 0) < BuildConfig.VERSION_CODE) { + mSharedPreferences.edit().remove(KEY_DEPRECATED_VERSION_CODE) + .putBoolean(KEY_DEPRECATED, false) + .apply(); + } + mDeprecated = mSharedPreferences.getBoolean(KEY_DEPRECATED, false); + } + + + public void readDeprecatedFromPrefIfNeeded(Context context) { + if (mSharedPreferences == null) { + readDeprecatedFromPref(context); + } + } + + public boolean isCurrentVersionDeprecated() { + return mDeprecated; + } + + public VersionInfo getVersionInfo() { + return mVersionInfo; + } + + public String getCurrentVersionIssues() { + if (mVersionInfo == null) + return null; + VersionInfo.OldVersion oldVersion = mVersionInfo.getOldVersion(BuildConfig.VERSION_CODE); + if (oldVersion == null) + return null; + return oldVersion.issues; + } + + public Observable checkForUpdatesIfNeededAndUsingWifi(Context context) { + if (mVersionInfo == null) { + return checkUpdateIfUsingWifi(context); + } + return Observable.just(mVersionInfo); + + } + + private Observable checkUpdateIfUsingWifi(Context context) { + if (!NetworkUtils.isWifiAvailable(context)) { + return Observable.empty(); + } + Observable observable = checkForUpdates(); + observable.subscribe(new SimpleObserver() { + @Override + public void onNext(@NonNull VersionInfo versionInfo) { + if (versionInfo.isValid()) { + setVersionInfo(versionInfo); + } + } + + @Override + public void onError(@NonNull Throwable e) { + e.printStackTrace(); + } + }); + return observable; + } + + private void setVersionInfo(VersionInfo result) { + mDeprecated = BuildConfig.VERSION_CODE <= result.deprecated; + mVersionInfo = result; + if (mDeprecated) { + mSharedPreferences.edit().putBoolean(KEY_DEPRECATED, mDeprecated) + .putInt(KEY_DEPRECATED_VERSION_CODE, BuildConfig.VERSION_CODE) + .apply(); + } + } +} diff --git a/app/src/main/java/com/stardust/scriptdroid/network/entity/VersionInfo.java b/app/src/main/java/com/stardust/scriptdroid/network/entity/VersionInfo.java new file mode 100644 index 00000000..cf944f6d --- /dev/null +++ b/app/src/main/java/com/stardust/scriptdroid/network/entity/VersionInfo.java @@ -0,0 +1,78 @@ +package com.stardust.scriptdroid.network.entity; + +import android.text.TextUtils; + + +import org.json.JSONObject; + +import java.util.List; + +/** + * Created by Stardust on 2017/9/20. + */ + +public class VersionInfo { + + public int versionCode; + public String releaseNotes; + public String versionName; + public List downloads; + public List oldVersions; + public int deprecated; + public String downloadUrl; + + public boolean isValid() { + return downloads != null && !downloads.isEmpty() && versionCode > 0 + && !TextUtils.isEmpty(versionName) && !TextUtils.isEmpty(releaseNotes); + } + + public OldVersion getOldVersion(int versionCode) { + for (OldVersion oldVersion : oldVersions) { + if (oldVersion.versionCode == versionCode) { + return oldVersion; + } + } + return null; + } + + @Override + public String toString() { + return "UpdateInfo{" + + "versionCode=" + versionCode + + ", releaseNotes='" + releaseNotes + '\'' + + ", versionName='" + versionName + '\'' + + ", downloads=" + downloads + + ", oldVersions=" + oldVersions + + ", deprecated=" + deprecated + + ", downloadUrl='" + downloadUrl + '\'' + + '}'; + } + + public static class OldVersion extends JSONObject { + + public int versionCode; + public String issues; + + @Override + public String toString() { + return "OldVersion{" + + "versionCode=" + versionCode + + ", issues='" + issues + '\'' + + '}'; + } + } + + public static class Download extends JSONObject { + + public String name; + public String url; + + @Override + public String toString() { + return "Download{" + + "name='" + name + '\'' + + ", url='" + url + '\'' + + '}'; + } + } +} diff --git a/app/src/main/java/com/stardust/scriptdroid/sublime/SublimePluginClient.java b/app/src/main/java/com/stardust/scriptdroid/sublime/SublimePluginClient.java index cbd18af5..898c841b 100644 --- a/app/src/main/java/com/stardust/scriptdroid/sublime/SublimePluginClient.java +++ b/app/src/main/java/com/stardust/scriptdroid/sublime/SublimePluginClient.java @@ -5,6 +5,8 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParser; import org.greenrobot.eventbus.EventBus; +import org.reactivestreams.Publisher; +import org.reactivestreams.Subscriber; import java.io.BufferedReader; import java.io.IOException; @@ -12,9 +14,10 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.Socket; -import java.util.concurrent.Executor; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; +import java.util.concurrent.Callable; + +import io.reactivex.Observable; +import io.reactivex.subjects.PublishSubject; /** * Created by Stardust on 2017/5/10. @@ -22,50 +25,56 @@ import java.util.concurrent.Executors; public class SublimePluginClient { - public static class ConnectionStateChangeEvent { - - private boolean mConnected; - - public ConnectionStateChangeEvent(boolean connected) { - mConnected = connected; - } - - public boolean isConnected() { - return mConnected; - } - } private volatile Socket mSocket; private Handler mResponseHandler; private String host; private int port; private OutputStream mOutputStream; - private ExecutorService mExecutor; + private final PublishSubject mConnectionState; - public SublimePluginClient(String host, int port) { + public SublimePluginClient(String host, int port, PublishSubject connectionState) { this.host = host; this.port = port; + mConnectionState = connectionState; } public void setResponseHandler(Handler handler) { mResponseHandler = handler; } - public void listen() { + public Observable listen() { if (mSocket != null) { throw new IllegalStateException("Socket listening "); } + return Observable.fromPublisher(new Publisher() { + + @Override + public void subscribe(Subscriber s) { + if (mSocket != null) { + s.onError(new IllegalStateException("Socket listening ")); + return; + } + listenInternal(s); + } + }); + + } + + private void listenInternal(final Subscriber s) { new Thread(new Runnable() { @Override public void run() { try { mSocket = new Socket(host, port); - EventBus.getDefault().post(new ConnectionStateChangeEvent(true)); + mConnectionState.onNext(true); mSocket.setTcpNoDelay(true); mOutputStream = mSocket.getOutputStream(); - startReadLoop(mSocket.getInputStream()); + s.onComplete(); + readLoop(mSocket.getInputStream()); } catch (IOException e) { e.printStackTrace(); + s.onError(e); } finally { tryClose(); } @@ -73,6 +82,10 @@ public class SublimePluginClient { }).start(); } + public PublishSubject getConnectionState() { + return mConnectionState; + } + public boolean isListening() { return mSocket != null; } @@ -85,24 +98,17 @@ public class SublimePluginClient { } } - public void send(final JsonObject object) { + public Observable send(final JsonObject object) { if (mSocket == null) { throw new IllegalStateException("Socket is not listening "); } - if (mExecutor == null) { - mExecutor = Executors.newSingleThreadExecutor(); - } - mExecutor.execute(new Runnable() { + return Observable.fromCallable(new Callable() { @Override - public void run() { - try { - mOutputStream.write(object.toString().getBytes()); - mOutputStream.write("\n".getBytes()); - mOutputStream.flush(); - } catch (IOException e) { - e.printStackTrace(); - tryClose(); - } + public Void call() throws Exception { + mOutputStream.write(object.toString().getBytes()); + mOutputStream.write("\n".getBytes()); + mOutputStream.flush(); + return null; } }); } @@ -110,23 +116,22 @@ public class SublimePluginClient { public void close() throws IOException { if (mSocket != null) { mSocket.close(); - mExecutor.shutdownNow(); mSocket = null; mOutputStream = null; - mExecutor = null; - EventBus.getDefault().post(new ConnectionStateChangeEvent(false)); + mConnectionState.onNext(false); } } - private void startReadLoop(InputStream stream) throws IOException { + private void readLoop(InputStream stream) throws IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); + JsonParser parser = new JsonParser(); while (!Thread.currentThread().isInterrupted()) { String line = reader.readLine(); if (line == null) { return; } if (mResponseHandler != null) { - JsonElement jsonElement = new JsonParser().parse(line); + JsonElement jsonElement = parser.parse(line); JsonObject jsonObject = jsonElement.getAsJsonObject(); mResponseHandler.handle(jsonObject); } diff --git a/app/src/main/java/com/stardust/scriptdroid/sublime/SublimePluginService.java b/app/src/main/java/com/stardust/scriptdroid/sublime/SublimePluginService.java index a7d37eba..384a6b48 100644 --- a/app/src/main/java/com/stardust/scriptdroid/sublime/SublimePluginService.java +++ b/app/src/main/java/com/stardust/scriptdroid/sublime/SublimePluginService.java @@ -2,7 +2,8 @@ package com.stardust.scriptdroid.sublime; import com.google.gson.JsonObject; -import java.io.IOException; +import io.reactivex.Observable; +import io.reactivex.subjects.PublishSubject; /** * Created by Stardust on 2017/5/11. @@ -11,6 +12,7 @@ import java.io.IOException; public class SublimePluginService { private static SublimePluginClient client; + private static final PublishSubject CONNECTION_STATE = PublishSubject.create(); public static boolean isConnected() { return client != null && client.isListening(); @@ -25,17 +27,21 @@ public class SublimePluginService { public static void disconnect() { try { client.close(); - } catch (IOException e) { + } catch (Exception e) { e.printStackTrace(); } finally { client = null; } } - public static void connect(String host) { - client = new SublimePluginClient(host, 1209); + public static PublishSubject getConnectionState() { + return CONNECTION_STATE; + } + + public static Observable connect(String host) { + client = new SublimePluginClient(host, 1209, CONNECTION_STATE); client.setResponseHandler(new SublimeResponseHandler()); - client.listen(); + return client.listen(); } public static void log(String log) { @@ -46,8 +52,9 @@ public class SublimePluginService { object.addProperty("log", log); try { client.send(object); - } catch (IllegalStateException e) { + } catch (Exception e) { e.printStackTrace(); + disconnect(); } } } diff --git a/app/src/main/java/com/stardust/scriptdroid/tool/UpdateChecker.java b/app/src/main/java/com/stardust/scriptdroid/tool/UpdateChecker.java deleted file mode 100644 index 20868c2d..00000000 --- a/app/src/main/java/com/stardust/scriptdroid/tool/UpdateChecker.java +++ /dev/null @@ -1,169 +0,0 @@ -package com.stardust.scriptdroid.tool; - -import android.content.Context; -import android.text.TextUtils; -import android.util.Log; - -import com.android.volley.DefaultRetryPolicy; -import com.android.volley.Request; -import com.android.volley.RequestQueue; -import com.android.volley.Response; -import com.android.volley.VolleyError; -import com.android.volley.toolbox.StringRequest; -import com.android.volley.toolbox.Volley; -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; -import com.stardust.scriptdroid.BuildConfig; - -import org.json.JSONObject; - -import java.lang.reflect.Type; -import java.util.List; - -/** - * Created by Stardust on 2017/4/9. - */ - -public class UpdateChecker implements Response.Listener, Response.ErrorListener { - - private static final String LOG_TAG = UpdateChecker.class.getName(); - private RequestQueue mRequestQueue; - private static final String UPDATE_URL = "https://raw.githubusercontent.com/hyb1996/NoRootScriptDroid/master/version.json"; - - public interface Callback { - - void onSuccess(UpdateInfo result); - - void onError(Exception exception); - - } - - public static UpdateInfo savedResult; - - - private final int mTimeOut = 3000; - private Callback mCallback; - - public UpdateChecker(Context context) { - mRequestQueue = Volley.newRequestQueue(context); - } - - private UpdateInfo parse(String json) { - Gson gson = new Gson(); - Type type = new TypeToken() { - }.getType(); - UpdateInfo result = gson.fromJson(json, type); - Log.i(LOG_TAG, result.toString()); - return result; - } - - - public void check(final Callback callback) { - mCallback = callback; - StringRequest request = new StringRequest(Request.Method.GET, UPDATE_URL, this, this); - request.setRetryPolicy(new DefaultRetryPolicy(mTimeOut, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT)); - request.setTag("update-check"); - request.setShouldCache(false); - mRequestQueue.add(request); - } - - @Override - public void onErrorResponse(VolleyError error) { - error.printStackTrace(); - mCallback.onError(error); - mCallback = null; - } - - @Override - public void onResponse(String response) { - try { - UpdateInfo result = parse(response); - savedResult = result; - if (mCallback == null) - return; - if (result.isValid()) { - mCallback.onSuccess(result); - } else { - mCallback.onError(new UpdateDataInvalidException()); - } - } catch (Exception e) { - e.printStackTrace(); - mCallback.onError(e); - } - mCallback = null; - } - - public void cancel() { - mRequestQueue.cancelAll("update-check"); - } - - public static class UpdateInfo extends JSONObject { - - public int versionCode; - public String releaseNotes; - public String versionName; - public List downloads; - public List oldVersions; - public int deprecated; - public String downloadUrl; - - public boolean isValid() { - return downloads != null && !downloads.isEmpty() && versionCode > 0 - && !TextUtils.isEmpty(versionName) && !TextUtils.isEmpty(releaseNotes); - } - - public OldVersion getOldVersion(int versionCode) { - for (OldVersion oldVersion : oldVersions) { - if (oldVersion.versionCode == versionCode) { - return oldVersion; - } - } - return null; - } - - @Override - public String toString() { - return "UpdateInfo{" + - "versionCode=" + versionCode + - ", releaseNotes='" + releaseNotes + '\'' + - ", versionName='" + versionName + '\'' + - ", downloads=" + downloads + - ", oldVersions=" + oldVersions + - ", deprecated=" + deprecated + - ", downloadUrl='" + downloadUrl + '\'' + - '}'; - } - } - - public static class OldVersion extends JSONObject { - - public int versionCode; - public String issues; - - @Override - public String toString() { - return "OldVersion{" + - "versionCode=" + versionCode + - ", issues='" + issues + '\'' + - '}'; - } - } - - public static class Download extends JSONObject { - - public String name; - public String url; - - @Override - public String toString() { - return "Download{" + - "name='" + name + '\'' + - ", url='" + url + '\'' + - '}'; - } - } - - public static class UpdateDataInvalidException extends RuntimeException { - - } -} diff --git a/app/src/main/java/com/stardust/scriptdroid/tool/VersionInfo.java b/app/src/main/java/com/stardust/scriptdroid/tool/VersionInfo.java deleted file mode 100644 index d11109bb..00000000 --- a/app/src/main/java/com/stardust/scriptdroid/tool/VersionInfo.java +++ /dev/null @@ -1,121 +0,0 @@ -package com.stardust.scriptdroid.tool; - -import android.content.Context; -import android.content.SharedPreferences; -import android.preference.PreferenceManager; - -import com.stardust.scriptdroid.BuildConfig; -import com.stardust.util.NetworkUtils; - -/** - * Created by Stardust on 2017/4/9. - */ - -public class VersionInfo { - - - private static final String KEY_DEPRECATED = "Still loving you...Can we go back..."; - private static final String KEY_DEPRECATED_VERSION_CODE = "I miss you so much tonight...Baby don't let me cry..."; - - public interface OnReceiveUpdateResultCallback { - void onReceive(UpdateChecker.UpdateInfo info, boolean isCurrentVersionDeprecated); - } - - - private static VersionInfo instance = new VersionInfo(); - - public static VersionInfo getInstance() { - return instance; - } - - private boolean mDeprecated = false; - private UpdateChecker.UpdateInfo mUpdateInfo; - private OnReceiveUpdateResultCallback mOnReceiveUpdateResultCallback; - private SharedPreferences mSharedPreferences; - - public void readDeprecatedFromPref(Context context) { - mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(context); - if (mSharedPreferences.getInt(KEY_DEPRECATED_VERSION_CODE, 0) < BuildConfig.VERSION_CODE) { - mSharedPreferences.edit().remove(KEY_DEPRECATED_VERSION_CODE) - .putBoolean(KEY_DEPRECATED, false) - .apply(); - } - mDeprecated = mSharedPreferences.getBoolean(KEY_DEPRECATED, false); - } - - - public void readDeprecatedFromPrefIfNeeded(Context context) { - if (mSharedPreferences == null) { - readDeprecatedFromPref(context); - } - } - - public boolean isCurrentVersionDeprecated() { - return mDeprecated; - } - - public UpdateChecker.UpdateInfo getUpdateInfo() { - return mUpdateInfo; - } - - public String getCurrentVersionIssues() { - if (mUpdateInfo == null) - return null; - UpdateChecker.OldVersion oldVersion = mUpdateInfo.getOldVersion(BuildConfig.VERSION_CODE); - if (oldVersion == null) - return null; - return oldVersion.issues; - } - - public void checkUpdateIfNeeded(Context context) { - if (mUpdateInfo == null) { - checkUpdateIfUsingWifi(context); - } - } - - public void setOnReceiveUpdateResultCallback(OnReceiveUpdateResultCallback onReceiveUpdateResultCallback) { - mOnReceiveUpdateResultCallback = onReceiveUpdateResultCallback; - } - - private void checkUpdateIfUsingWifi(Context context) { - if (NetworkUtils.isWifiAvailable(context)) { - checkUpdate(context); - } - - } - - public void checkUpdate(Context context) { - checkUpdateInner(context); - } - - private void checkUpdateInner(final Context context) { - new UpdateChecker(context).check(new UpdateChecker.Callback() { - - @Override - public void onSuccess(UpdateChecker.UpdateInfo result) { - if (result.isValid()) { - setUpdateInfo(result); - } - } - - @Override - public void onError(Exception exception) { - exception.printStackTrace(); - } - }); - } - - private void setUpdateInfo(UpdateChecker.UpdateInfo result) { - mDeprecated = BuildConfig.VERSION_CODE <= result.deprecated; - mUpdateInfo = result; - if (mDeprecated) { - mSharedPreferences.edit().putBoolean(KEY_DEPRECATED, mDeprecated) - .putInt(KEY_DEPRECATED_VERSION_CODE, BuildConfig.VERSION_CODE) - .apply(); - } - if (mOnReceiveUpdateResultCallback != null) { - mOnReceiveUpdateResultCallback.onReceive(result, mDeprecated); - } - } - -} diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/BaseActivity.java b/app/src/main/java/com/stardust/scriptdroid/ui/BaseActivity.java index 586f1600..c8102d3d 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/BaseActivity.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/BaseActivity.java @@ -11,7 +11,7 @@ import android.support.v7.widget.Toolbar; import android.view.View; import com.stardust.scriptdroid.R; -import com.stardust.scriptdroid.tool.VersionInfo; +import com.stardust.scriptdroid.network.VersionService; import com.stardust.theme.ThemeColorManager; import com.stardust.util.BackPressedHandler; @@ -46,18 +46,6 @@ public abstract class BaseActivity extends AppCompatActivity implements BackPres } - @Override - protected void onResume() { - super.onResume(); - } - - - @Override - protected void onPause() { - super.onPause(); - VersionInfo.getInstance().setOnReceiveUpdateResultCallback(null); - } - @SuppressWarnings("unchecked") public T $(int resId) { return (T) findViewById(resId); diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/main/MainActivity.java b/app/src/main/java/com/stardust/scriptdroid/ui/main/MainActivity.java index 203af604..7b04dfa0 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/main/MainActivity.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/main/MainActivity.java @@ -28,7 +28,6 @@ import com.stardust.scriptdroid.R; import com.stardust.scriptdroid.autojs.AutoJs; import com.stardust.scriptdroid.external.floatingwindow.HoverMenuManger; import com.stardust.scriptdroid.script.StorageFileProvider; -import com.stardust.scriptdroid.ui.main.community.CommunityFragment; import com.stardust.scriptdroid.ui.main.community.CommunityFragment_; import com.stardust.scriptdroid.ui.main.doc.OnlineDocsFragment_; import com.stardust.scriptdroid.ui.main.scripts.MyScriptListFragment_; @@ -194,7 +193,7 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega @Override protected void onResume() { super.onResume(); - mVersionGuard.checkDeprecateAndUpdate(); + mVersionGuard.checkForDeprecatesAndUpdates(); } @Override diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/main/community/CommunityFragment.java b/app/src/main/java/com/stardust/scriptdroid/ui/main/community/CommunityFragment.java index a123ef39..7fc76d17 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/main/community/CommunityFragment.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/main/community/CommunityFragment.java @@ -44,7 +44,7 @@ public class CommunityFragment extends ViewPagerFragment implements BackPressedH @AfterViews void setUpViews() { mWebView = mEWebView.getWebView(); - mWebView.loadUrl("http://39.108.231.37/"); + mWebView.loadUrl("http://www.autojs.org/"); } @Override diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/main/drawer/DrawerFragment.java b/app/src/main/java/com/stardust/scriptdroid/ui/main/drawer/DrawerFragment.java index 899dcafe..d7a10f4c 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/main/drawer/DrawerFragment.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/main/drawer/DrawerFragment.java @@ -1,13 +1,10 @@ package com.stardust.scriptdroid.ui.main.drawer; +import android.content.DialogInterface; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; -import android.support.v7.widget.SwitchCompat; -import android.view.MenuInflater; -import android.view.MenuItem; import android.view.View; -import android.widget.CompoundButton; import android.widget.Toast; import com.afollestad.materialdialogs.DialogAction; @@ -17,10 +14,15 @@ import com.stardust.scriptdroid.Pref; import com.stardust.scriptdroid.R; import com.stardust.scriptdroid.external.floatingwindow.HoverMenuManger; import com.stardust.scriptdroid.external.floatingwindow.menu.HoverMenuService; +import com.stardust.scriptdroid.network.UpdateCheckApi; +import com.stardust.scriptdroid.network.VersionService; +import com.stardust.scriptdroid.network.entity.VersionInfo; +import com.stardust.scriptdroid.tool.SimpleObserver; import com.stardust.scriptdroid.ui.common.ProgressDialog; +import com.stardust.scriptdroid.ui.settings.SettingsActivity; +import com.stardust.scriptdroid.ui.update.UpdateInfoDialogBuilder; import com.stardust.theme.ThemeColorManager; import com.stardust.view.accessibility.AccessibilityService; -import com.stardust.scriptdroid.sublime.SublimePluginClient; import com.stardust.scriptdroid.sublime.SublimePluginService; import com.stardust.scriptdroid.tool.AccessibilityServiceTool; import com.stardust.scriptdroid.tool.WifiTool; @@ -28,15 +30,18 @@ import com.stardust.util.IntentUtil; import com.stardust.util.UnderuseExecutors; import org.androidannotations.annotations.AfterViews; -import org.androidannotations.annotations.CheckedChange; import org.androidannotations.annotations.Click; import org.androidannotations.annotations.EFragment; import org.androidannotations.annotations.ViewById; -import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; -import org.greenrobot.eventbus.ThreadMode; -import java.util.concurrent.Executor; +import java.util.concurrent.Callable; + +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.Consumer; +import io.reactivex.schedulers.Schedulers; /** @@ -45,153 +50,234 @@ import java.util.concurrent.Executor; @EFragment(R.layout.fragment_drawer) public class DrawerFragment extends android.support.v4.app.Fragment { - SwitchCompat mAccessibilityServiceSwitch; - SwitchCompat mFloatingWindowSwitch; - SwitchCompat mDebugSwitch; + private static final String URL_SUBLIME_PLUGIN_HELP = "https://github.com/hyb1996/AutoJs-Sublime-Plugin/blob/master/Readme.md"; + + @ViewById(R.id.debug) + DrawerMenuItem mConnectionItem; + + @ViewById(R.id.accessibility_service) + DrawerMenuItem mAccessibilityServiceItem; + + @ViewById(R.id.floating_window) + DrawerMenuItem mFloatingWindowItem; + + @ViewById(R.id.check_for_updates) + DrawerMenuItem mCheckForUpdatesItem; + @ViewById(R.id.header) View mHeaderView; - private Executor mExecutor = UnderuseExecutors.getExecutor(); + + + private Disposable mConnectionStateDisposable; @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); - EventBus.getDefault().register(this); + mConnectionStateDisposable = SublimePluginService.getConnectionState() + .observeOn(AndroidSchedulers.mainThread()) + .doOnNext(new Consumer() { + @Override + public void accept(@io.reactivex.annotations.NonNull Boolean connected) throws Exception { + mConnectionItem.getSwitchCompat().setChecked(connected); + } + }) + .subscribe(); } @Override public void onStart() { super.onStart(); - //syncSwitchState(); + syncSwitchState(); } @AfterViews - void setUpViews(){ + void setUpViews() { ThemeColorManager.addViewBackground(mHeaderView); } - - private void syncSwitchState() { - mAccessibilityServiceSwitch.postDelayed(new Runnable() { - @Override - public void run() { - mExecutor.execute(new Runnable() { - @Override - public void run() { - if (mAccessibilityServiceSwitch == null) { - return; - } - final boolean checked = AccessibilityServiceTool.isAccessibilityServiceEnabled(App.getApp()); - mAccessibilityServiceSwitch.post(new Runnable() { - @Override - public void run() { - if (mAccessibilityServiceSwitch == null) { - return; - } - mAccessibilityServiceSwitch.setChecked(checked); - } - }); - } - }); - } - }, 450); - mFloatingWindowSwitch.setChecked(HoverMenuManger.isHoverMenuShowing()); - } - - void setAutoOperateServiceEnable(CompoundButton button, boolean enable) { - boolean isAccessibilityServiceEnabled = AccessibilityServiceTool.isAccessibilityServiceEnabled(App.getApp()); - if (enable && !isAccessibilityServiceEnabled) { + @Click(R.id.accessibility_service) + void enableOrDisableAccessibilityService() { + boolean isAccessibilityServiceEnabled = isAccessibilityServiceEnabled(); + boolean checked = mAccessibilityServiceItem.getSwitchCompat().isChecked(); + if (checked && !isAccessibilityServiceEnabled) { enableAccessibilityService(); - } else if (!enable && isAccessibilityServiceEnabled) { + } else if (!checked && isAccessibilityServiceEnabled) { if (!AccessibilityService.disable()) { AccessibilityServiceTool.goToAccessibilitySetting(); } } } + private boolean isAccessibilityServiceEnabled() { + return AccessibilityServiceTool.isAccessibilityServiceEnabled(getActivity()); + } + + @Click(R.id.floating_window) + void showOrDismissFloatingWindow() { + boolean isFloatingWindowShowing = HoverMenuManger.isHoverMenuShowing(); + boolean checked = mFloatingWindowItem.getSwitchCompat().isChecked(); + if (checked && !isFloatingWindowShowing) { + HoverMenuManger.showHoverMenu(); + enableAccessibilityServiceByRootIfNeeded(); + } else if (!checked && isFloatingWindowShowing) { + HoverMenuManger.hideHoverMenu(); + } + } + + @Click(R.id.theme_color) + void openThemeColorSettings() { + SettingsActivity.selectThemeColor(getActivity()); + } + + private void enableAccessibilityServiceByRootIfNeeded() { + Observable.fromCallable(new Callable() { + @Override + public Boolean call() throws Exception { + return Pref.enableAccessibilityServiceByRoot() && !isAccessibilityServiceEnabled(); + } + }) + .subscribeOn(Schedulers.computation()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Consumer() { + @Override + public void accept(@io.reactivex.annotations.NonNull Boolean needed) throws Exception { + if (needed) { + enableAccessibilityServiceByRoot(); + } + } + }); + + } + + @Click(R.id.debug) + void connectOrDisconnectToRemote() { + boolean checked = mConnectionItem.getSwitchCompat().isChecked(); + boolean connected = SublimePluginService.isConnected(); + if (checked && !connected) { + inputRemoteHost(); + } else if (!checked && connected) { + SublimePluginService.disconnectIfNeeded(); + } + } + + private void inputRemoteHost() { + String host = Pref.getServerAddressOrDefault(WifiTool.getWifiAddress(getActivity())); + new MaterialDialog.Builder(getActivity()) + .title(R.string.text_server_address) + .input("", host, new MaterialDialog.InputCallback() { + @Override + public void onInput(@NonNull MaterialDialog dialog, CharSequence input) { + Pref.saveServerAddress(input.toString()); + connectToRemote(input.toString()); + } + }) + .neutralText(R.string.text_help) + .onNeutral(new MaterialDialog.SingleButtonCallback() { + @Override + public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) { + IntentUtil.browse(getActivity(), URL_SUBLIME_PLUGIN_HELP); + } + }) + .cancelListener(new DialogInterface.OnCancelListener() { + @Override + public void onCancel(DialogInterface dialog) { + mConnectionItem.getSwitchCompat().toggle(false); + } + }) + .show(); + } + + private void connectToRemote(String host) { + mConnectionItem.setProgress(true); + Toast.makeText(App.getApp(), R.string.text_connecting, Toast.LENGTH_SHORT).show(); + SublimePluginService.connect(host) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new SimpleObserver() { + + @Override + public void onError(@io.reactivex.annotations.NonNull Throwable e) { + Toast.makeText(App.getApp(), e.getMessage(), Toast.LENGTH_SHORT).show(); + mConnectionItem.getSwitchCompat().setChecked(false, false); + mConnectionItem.setProgress(false); + } + + @Override + public void onComplete() { + mConnectionItem.setProgress(false); + } + }); + } + + @Click(R.id.check_for_updates) + void checkForUpdates() { + mCheckForUpdatesItem.setProgress(true); + VersionService.getInstance().checkForUpdates() + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new SimpleObserver() { + + @Override + public void onNext(@io.reactivex.annotations.NonNull VersionInfo versionInfo) { + new UpdateInfoDialogBuilder(getActivity(), versionInfo) + .show(); + mCheckForUpdatesItem.setProgress(false); + } + + @Override + public void onError(@io.reactivex.annotations.NonNull Throwable e) { + e.printStackTrace(); + Toast.makeText(App.getApp(), R.string.text_check_update_error, Toast.LENGTH_SHORT).show(); + mCheckForUpdatesItem.setProgress(false); + } + }); + } + + + private void syncSwitchState() { + mAccessibilityServiceItem.getSwitchCompat().setChecked( + AccessibilityServiceTool.isAccessibilityServiceEnabled(getActivity())); + mFloatingWindowItem.getSwitchCompat().setChecked(HoverMenuManger.isHoverMenuShowing()); + } + private void enableAccessibilityService() { if (!Pref.enableAccessibilityServiceByRoot()) { AccessibilityServiceTool.goToAccessibilitySetting(); return; } enableAccessibilityServiceByRoot(); - } private void enableAccessibilityServiceByRoot() { - final ProgressDialog progress = new ProgressDialog(getContext(), R.string.text_enable_accessibility_service_by_root_ing); - UnderuseExecutors.execute(new Runnable() { + mAccessibilityServiceItem.setProgress(true); + Observable.fromCallable(new Callable() { @Override - public void run() { - final boolean succeed = AccessibilityServiceTool.enableAccessibilityServiceByRootAndWaitFor(4000); - getActivity().runOnUiThread(new Runnable() { + public Boolean call() throws Exception { + return AccessibilityServiceTool.enableAccessibilityServiceByRootAndWaitFor(4000); + } + }) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Consumer() { @Override - public void run() { + public void accept(@io.reactivex.annotations.NonNull Boolean succeed) throws Exception { if (!succeed) { Toast.makeText(getContext(), R.string.text_enable_accessibitliy_service_by_root_failed, Toast.LENGTH_SHORT).show(); AccessibilityServiceTool.goToAccessibilitySetting(); } - progress.dismiss(); + mAccessibilityServiceItem.setProgress(false); } }); - } - }); - } - - void setFloatingWindowEnable(CompoundButton button, boolean enable) { - if (enable && !HoverMenuManger.isHoverMenuShowing()) { - HoverMenuManger.showHoverMenu(); - if (Pref.enableAccessibilityServiceByRoot()) { - enableAccessibilityServiceByRoot(); - } - } else if (!enable && HoverMenuManger.isHoverMenuShowing()) { - HoverMenuManger.hideHoverMenu(); - } - } - - void setDebugEnabled(CompoundButton button, boolean enabled) { - if (enabled && !SublimePluginService.isConnected()) { - new MaterialDialog.Builder(getActivity()) - .title(R.string.text_server_address) - .input("", getServerAddress(), new MaterialDialog.InputCallback() { - @Override - public void onInput(@NonNull MaterialDialog dialog, CharSequence input) { - Pref.saveServerAddress(input.toString()); - SublimePluginService.connect(input.toString()); - } - }) - .neutralText(R.string.text_help) - .onNeutral(new MaterialDialog.SingleButtonCallback() { - @Override - public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) { - IntentUtil.browse(getActivity(), "https://github.com/hyb1996/AutoJs-Sublime-Plugin/blob/master/Readme.md"); - } - }) - .show(); - } else if (!enabled) { - SublimePluginService.disconnectIfNeeded(); - } - } - - private CharSequence getServerAddress() { - return Pref.getServerAddressOrDefault(WifiTool.getWifiAddress(getActivity())); } @Override public void onDestroy() { super.onDestroy(); - EventBus.getDefault().unregister(this); + mConnectionStateDisposable.dispose(); } @Subscribe public void onHoverMenuServiceStateChanged(HoverMenuService.ServiceStateChangedEvent event) { - mFloatingWindowSwitch.setChecked(event.state); + mAccessibilityServiceItem.getSwitchCompat().setChecked(event.state); } - - @Subscribe(threadMode = ThreadMode.MAIN) - public void onSublimeClientStateChange(SublimePluginClient.ConnectionStateChangeEvent event) { - mDebugSwitch.setChecked(event.isConnected()); - App.getApp().getUiHandler().toast(event.isConnected() ? R.string.text_connected : R.string.text_disconnected); - } - } diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/main/drawer/DrawerMenuItem.java b/app/src/main/java/com/stardust/scriptdroid/ui/main/drawer/DrawerMenuItem.java index 05b3cb36..d8748827 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/main/drawer/DrawerMenuItem.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/main/drawer/DrawerMenuItem.java @@ -2,26 +2,49 @@ package com.stardust.scriptdroid.ui.main.drawer; import android.content.Context; import android.content.res.TypedArray; -import android.graphics.drawable.Drawable; import android.os.Build; import android.support.annotation.Nullable; import android.support.annotation.RequiresApi; -import android.support.v7.widget.SwitchCompat; import android.util.AttributeSet; import android.view.View; +import android.widget.AutoCompleteTextView; +import android.widget.CompoundButton; import android.widget.FrameLayout; import android.widget.ImageView; -import android.widget.LinearLayout; import android.widget.TextView; +import android.widget.Toast; import com.stardust.scriptdroid.R; +import com.stardust.widget.PrefSwitch; +import com.stardust.widget.SwitchCompat; + +import butterknife.BindView; +import butterknife.ButterKnife; +import me.zhanghai.android.materialprogressbar.MaterialProgressBar; /** * Created by Stardust on 2017/8/25. */ public class DrawerMenuItem extends FrameLayout { - private SwitchCompat mSwitchCompat; + private static final long CLICK_TIMEOUT = 1000; + + @BindView(R.id.sw) + PrefSwitch mSwitchCompat; + + @BindView(R.id.progress_bar) + MaterialProgressBar mProgressBar; + + @BindView(R.id.icon) + ImageView mIcon; + + @BindView(R.id.title) + TextView mTitle; + + + private OnClickListener mOnClickListener; + private boolean mAntiShake = false; + private long mLastClickMillis; public DrawerMenuItem(Context context) { super(context); @@ -46,28 +69,68 @@ public class DrawerMenuItem extends FrameLayout { private void init(AttributeSet attrs) { inflate(getContext(), R.layout.drawer_menu_item, this); - ImageView icon = (ImageView) findViewById(R.id.icon); - TextView title = (TextView) findViewById(R.id.title); - mSwitchCompat = (SwitchCompat) findViewById(R.id.sw); + ButterKnife.bind(this, this); if (attrs == null) return; TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.DrawerMenuItem); - icon.setImageResource(a.getResourceId(R.styleable.DrawerMenuItem_icon, 0)); - title.setText(a.getString(R.styleable.DrawerMenuItem_title)); + mIcon.setImageResource(a.getResourceId(R.styleable.DrawerMenuItem_icon, 0)); + mTitle.setText(a.getString(R.styleable.DrawerMenuItem_title)); + mAntiShake = a.getBoolean(R.styleable.DrawerMenuItem_anti_shake, false); if (a.getBoolean(R.styleable.DrawerMenuItem_with_switch, false)) { - mSwitchCompat.setVisibility(VISIBLE); - setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - mSwitchCompat.toggle(); - } - }); + enableSwitch(a.getString(R.styleable.DrawerMenuItem_pref_key)); } a.recycle(); } + private void enableSwitch(String prefKey) { + mSwitchCompat.setVisibility(VISIBLE); + if (prefKey != null) { + mSwitchCompat.setPrefKey(prefKey); + } + mSwitchCompat.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + onClick(); + } + }); + super.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + mSwitchCompat.toggle(); + } + }); + } + + private void onClick() { + if (mAntiShake && (System.currentTimeMillis() - mLastClickMillis < CLICK_TIMEOUT)) { + Toast.makeText(getContext(), R.string.text_click_too_frequently, Toast.LENGTH_SHORT).show(); + mSwitchCompat.setChecked(!mSwitchCompat.isChecked(), false); + return; + } + mLastClickMillis = System.currentTimeMillis(); + if (mOnClickListener != null) { + mOnClickListener.onClick(DrawerMenuItem.this); + } + } + + public void setProgress(boolean onProgress) { + mProgressBar.setVisibility(onProgress ? VISIBLE : GONE); + mIcon.setVisibility(onProgress ? GONE : VISIBLE); + mSwitchCompat.setEnabled(!onProgress); + setEnabled(!onProgress); + + } + public SwitchCompat getSwitchCompat() { return mSwitchCompat; } + @Override + public void setOnClickListener(OnClickListener onClickListener) { + if (mSwitchCompat.getVisibility() == VISIBLE) { + mOnClickListener = onClickListener; + } else { + super.setOnClickListener(onClickListener); + } + } } diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/settings/SettingsActivity.java b/app/src/main/java/com/stardust/scriptdroid/ui/settings/SettingsActivity.java index 792bf3c5..82b3f22b 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/settings/SettingsActivity.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/settings/SettingsActivity.java @@ -5,15 +5,16 @@ import android.content.Intent; import android.os.Bundle; import android.preference.Preference; import android.preference.PreferenceScreen; +import android.support.v4.util.Pair; import android.support.v7.widget.Toolbar; import android.view.View; import android.widget.Toast; +import com.stardust.scriptdroid.network.VersionService; import com.stardust.scriptdroid.ui.BaseActivity; import com.stardust.scriptdroid.ui.error.IssueReporterActivity; import com.stardust.scriptdroid.ui.splash.SplashActivity; import com.stardust.scriptdroid.ui.splash.SplashActivity_; -import com.stardust.scriptdroid.ui.update.UpdateCheckDialog; import com.stardust.theme.preference.ThemeColorPreferenceFragment; import com.stardust.util.IntentUtil; import com.stardust.util.MapEntries; @@ -24,6 +25,7 @@ import com.stardust.theme.util.ListBuilder; import org.androidannotations.annotations.AfterViews; import org.androidannotations.annotations.EActivity; +import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -37,30 +39,35 @@ import de.psdev.licensesdialog.licenses.License; @EActivity(R.layout.activity_settings) public class SettingsActivity extends BaseActivity { - private static final List COLOR_ITEMS; + private static final List> COLOR_ITEMS = new ListBuilder>() + .add(new Pair<>(R.color.theme_color_red, R.string.theme_color_red)) + .add(new Pair<>(R.color.theme_color_pink, R.string.theme_color_pink)) + .add(new Pair<>(R.color.theme_color_purple, R.string.theme_color_purple)) + .add(new Pair<>(R.color.theme_color_dark_purple, R.string.theme_color_dark_purple)) + .add(new Pair<>(R.color.theme_color_indigo, R.string.theme_color_indigo)) + .add(new Pair<>(R.color.theme_color_blue, R.string.theme_color_blue)) + .add(new Pair<>(R.color.theme_color_light_blue, R.string.theme_color_light_blue)) + .add(new Pair<>(R.color.theme_color_blue_green, R.string.theme_color_blue_green)) + .add(new Pair<>(R.color.theme_color_cyan, R.string.theme_color_cyan)) + .add(new Pair<>(R.color.theme_color_green, R.string.theme_color_green)) + .add(new Pair<>(R.color.theme_color_light_green, R.string.theme_color_light_green)) + .add(new Pair<>(R.color.theme_color_yellow_green, R.string.theme_color_yellow_green)) + .add(new Pair<>(R.color.theme_color_yellow, R.string.theme_color_yellow)) + .add(new Pair<>(R.color.theme_color_amber, R.string.theme_color_amber)) + .add(new Pair<>(R.color.theme_color_orange, R.string.theme_color_orange)) + .add(new Pair<>(R.color.theme_color_dark_orange, R.string.theme_color_dark_orange)) + .add(new Pair<>(R.color.theme_color_brown, R.string.theme_color_brown)) + .add(new Pair<>(R.color.theme_color_gray, R.string.theme_color_gray)) + .add(new Pair<>(R.color.theme_color_blue_gray, R.string.theme_color_blue_gray)) + .list(); - static { - COLOR_ITEMS = new ListBuilder() - .add(new ColorSelectActivity.ColorItem("基佬红", 0xFFF44336)) - .add(new ColorSelectActivity.ColorItem("基佬粉", 0xFFE91E63)) - .add(new ColorSelectActivity.ColorItem("基佬紫", 0xFF9C27B0)) - .add(new ColorSelectActivity.ColorItem("基深紫", 0xFF673AB7)) - .add(new ColorSelectActivity.ColorItem("基靛蓝", 0xFF3F51B5)) - .add(new ColorSelectActivity.ColorItem("基佬蓝", 0xFF2196F3)) - .add(new ColorSelectActivity.ColorItem("基亮蓝", 0xFF03A9F4)) - .add(new ColorSelectActivity.ColorItem("基蓝绿", 0xFF00BCD4)) - .add(new ColorSelectActivity.ColorItem("基佬青", 0xFF009688)) - .add(new ColorSelectActivity.ColorItem("基佬绿", 0xFF4CAF50)) - .add(new ColorSelectActivity.ColorItem("基亮绿", 0xFF8BC34A)) - .add(new ColorSelectActivity.ColorItem("基黄绿", 0xFFCDDC39)) - .add(new ColorSelectActivity.ColorItem("基佬黄", 0xFFFFEB3B)) - .add(new ColorSelectActivity.ColorItem("基琥珀", 0xFFFFC107)) - .add(new ColorSelectActivity.ColorItem("基佬橙", 0xFFFF9800)) - .add(new ColorSelectActivity.ColorItem("基深橙", 0xFFFF5722)) - .add(new ColorSelectActivity.ColorItem("基佬棕", 0xFF795548)) - .add(new ColorSelectActivity.ColorItem("基佬灰", 0xFF9E9E9E)) - .add(new ColorSelectActivity.ColorItem("基南灰", 0xFF607D8B)) - .list(); + public static void selectThemeColor(Context context) { + List colorItems = new ArrayList<>(COLOR_ITEMS.size()); + for (Pair item : COLOR_ITEMS) { + colorItems.add(new ColorSelectActivity.ColorItem(context.getString(item.second), + context.getResources().getColor(item.first))); + } + ColorSelectActivity.startColorSelect(context, context.getString(R.string.mt_color_picker_title), colorItems); } @AfterViews @@ -101,13 +108,13 @@ public class SettingsActivity extends BaseActivity { .entry(getString(R.string.text_theme_color), new Runnable() { @Override public void run() { - ColorSelectActivity.startColorSelect(getActivity(), getString(R.string.mt_color_picker_title), COLOR_ITEMS); + selectThemeColor(getActivity()); } }) .entry(getString(R.string.text_reset_background), new Runnable() { @Override public void run() { - // EventBus.getDefault().post(new MessageEvent(MainActivity.MESSAGE_CLEAR_BACKGROUND_SETTINGS)); + // EventBus.getDefault().post(new MessageEvent(MainActivity.MESSAGE_CLEAR_BACKGROUND_SETTINGS)); Toast.makeText(getActivity(), R.string.text_already_reset, Toast.LENGTH_SHORT).show(); } }) @@ -123,7 +130,7 @@ public class SettingsActivity extends BaseActivity { .entry(getString(R.string.text_check_for_updates), new Runnable() { @Override public void run() { - new UpdateCheckDialog(getActivity()).show(); + VersionService.getInstance().checkForUpdatesAndShow(getActivity()); } }) .entry(getString(R.string.text_issue_report), new Runnable() { diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/update/UpdateCheckDialog.java b/app/src/main/java/com/stardust/scriptdroid/ui/update/UpdateCheckDialog.java deleted file mode 100644 index ce32fada..00000000 --- a/app/src/main/java/com/stardust/scriptdroid/ui/update/UpdateCheckDialog.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.stardust.scriptdroid.ui.update; - -import android.content.Context; -import android.support.annotation.NonNull; -import android.widget.Toast; - -import com.afollestad.materialdialogs.DialogAction; -import com.afollestad.materialdialogs.MaterialDialog; -import com.stardust.scriptdroid.BuildConfig; -import com.stardust.scriptdroid.R; -import com.stardust.scriptdroid.tool.UpdateChecker; -import com.stardust.util.IntentUtil; - -import java.util.LinkedList; - -/** - * Created by Stardust on 2017/4/9. - */ - -public class UpdateCheckDialog implements UpdateChecker.Callback { - - private MaterialDialog mProgressDialog; - private Context mContext; - private UpdateChecker mUpdateChecker; - - - public UpdateCheckDialog(Context context) { - mContext = context; - mUpdateChecker = new UpdateChecker(context); - } - - public void show() { - if (mProgressDialog != null) - throw new IllegalStateException(); - mProgressDialog = new MaterialDialog.Builder(mContext) - .content(mContext.getString(R.string.text_checking_update)) - .progress(true, 0) - .cancelable(false) - .show(); - mUpdateChecker.check(this); - } - - @Override - public void onSuccess(UpdateChecker.UpdateInfo result) { - mProgressDialog.dismiss(); - if (BuildConfig.VERSION_CODE >= result.versionCode) { - Toast.makeText(mContext, R.string.text_is_latest_version, Toast.LENGTH_SHORT).show(); - return; - } - new UpdateInfoDialogBuilder(mContext, result) - .show(); - clear(); - } - - @Override - public void onError(Exception exception) { - mProgressDialog.dismiss(); - Toast.makeText(mContext, R.string.text_check_update_error, Toast.LENGTH_SHORT).show(); - clear(); - } - - private void clear() { - mProgressDialog = null; - mContext = null; - } - -} diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/update/UpdateInfoDialogBuilder.java b/app/src/main/java/com/stardust/scriptdroid/ui/update/UpdateInfoDialogBuilder.java index 712e6bb6..5ec84a6b 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/update/UpdateInfoDialogBuilder.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/update/UpdateInfoDialogBuilder.java @@ -16,9 +16,9 @@ import android.widget.Toast; import com.afollestad.materialdialogs.MaterialDialog; import com.stardust.scriptdroid.BuildConfig; import com.stardust.scriptdroid.R; +import com.stardust.scriptdroid.network.entity.VersionInfo; import com.stardust.scriptdroid.script.StorageFileProvider; import com.stardust.scriptdroid.tool.IntentTool; -import com.stardust.scriptdroid.tool.UpdateChecker; import com.stardust.util.DownloadTask; import com.stardust.util.IntentUtil; import com.stardust.widget.CommonMarkdownView; @@ -32,16 +32,16 @@ public class UpdateInfoDialogBuilder extends MaterialDialog.Builder { private static final String KEY_DO_NOT_ASK_AGAIN_FOR_VERSION = "I cannot forget you...cannot help missing you..."; private View mView; private SharedPreferences mSharedPreferences; - private UpdateChecker.UpdateInfo mUpdateInfo; + private VersionInfo mVersionInfo; - public UpdateInfoDialogBuilder(@NonNull Context context, UpdateChecker.UpdateInfo info) { + public UpdateInfoDialogBuilder(@NonNull Context context, VersionInfo info) { super(context); mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(context); updateInfo(info); } - public UpdateInfoDialogBuilder updateInfo(UpdateChecker.UpdateInfo info) { - mUpdateInfo = info; + public UpdateInfoDialogBuilder updateInfo(VersionInfo info) { + mVersionInfo = info; mView = View.inflate(context, R.layout.dialog_update_info, null); setReleaseNotes(mView, info); setCurrentVersionIssues(mView, info); @@ -57,7 +57,7 @@ public class UpdateInfoDialogBuilder extends MaterialDialog.Builder { checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - mSharedPreferences.edit().putBoolean(KEY_DO_NOT_ASK_AGAIN_FOR_VERSION + mUpdateInfo.versionCode, isChecked).apply(); + mSharedPreferences.edit().putBoolean(KEY_DO_NOT_ASK_AGAIN_FOR_VERSION + mVersionInfo.versionCode, isChecked).apply(); } }); return this; @@ -65,15 +65,15 @@ public class UpdateInfoDialogBuilder extends MaterialDialog.Builder { @Override public MaterialDialog show() { - if (mSharedPreferences.getBoolean(KEY_DO_NOT_ASK_AGAIN_FOR_VERSION + mUpdateInfo.versionCode, false)) { + if (mSharedPreferences.getBoolean(KEY_DO_NOT_ASK_AGAIN_FOR_VERSION + mVersionInfo.versionCode, false)) { return null; } return super.show(); } - private void setCurrentVersionIssues(View view, UpdateChecker.UpdateInfo info) { + private void setCurrentVersionIssues(View view, VersionInfo info) { TextView issues = (TextView) view.findViewById(R.id.issues); - UpdateChecker.OldVersion currentVersion = info.getOldVersion(BuildConfig.VERSION_CODE); + VersionInfo.OldVersion currentVersion = info.getOldVersion(BuildConfig.VERSION_CODE); if (currentVersion == null) { issues.setVisibility(View.GONE); } else { @@ -81,10 +81,10 @@ public class UpdateInfoDialogBuilder extends MaterialDialog.Builder { } } - private void setUpdateDownloadButtons(View view, UpdateChecker.UpdateInfo info) { + private void setUpdateDownloadButtons(View view, VersionInfo info) { LinearLayout downloads = (LinearLayout) view.findViewById(R.id.downloads); setDirectlyDownloadButton(downloads, info); - for (final UpdateChecker.Download download : info.downloads) { + for (final VersionInfo.Download download : info.downloads) { Button button = (Button) View.inflate(getContext(), R.layout.dialog_update_info_btn, null); button.setText(download.name); downloads.addView(button); @@ -97,7 +97,7 @@ public class UpdateInfoDialogBuilder extends MaterialDialog.Builder { } } - private void setDirectlyDownloadButton(LinearLayout container, final UpdateChecker.UpdateInfo info) { + private void setDirectlyDownloadButton(LinearLayout container, final VersionInfo info) { if (TextUtils.isEmpty(info.downloadUrl)) { return; } @@ -139,7 +139,7 @@ public class UpdateInfoDialogBuilder extends MaterialDialog.Builder { task.execute(downloadUrl, path); } - private void setReleaseNotes(View view, UpdateChecker.UpdateInfo info) { + private void setReleaseNotes(View view, VersionInfo info) { CommonMarkdownView markdownView = (CommonMarkdownView) view.findViewById(R.id.release_notes); markdownView.loadMarkdown(info.releaseNotes); } diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/update/VersionGuard.java b/app/src/main/java/com/stardust/scriptdroid/ui/update/VersionGuard.java index b4845da4..f202ca11 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/update/VersionGuard.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/update/VersionGuard.java @@ -8,8 +8,11 @@ import com.afollestad.materialdialogs.DialogAction; import com.afollestad.materialdialogs.MaterialDialog; import com.stardust.scriptdroid.BuildConfig; import com.stardust.scriptdroid.R; -import com.stardust.scriptdroid.tool.UpdateChecker; -import com.stardust.scriptdroid.tool.VersionInfo; +import com.stardust.scriptdroid.network.VersionService; +import com.stardust.scriptdroid.network.entity.VersionInfo; +import com.stardust.scriptdroid.tool.SimpleObserver; + +import io.reactivex.functions.Consumer; /** * Created by Stardust on 2017/4/12. @@ -17,42 +20,40 @@ import com.stardust.scriptdroid.tool.VersionInfo; public class VersionGuard { - private Activity mActivity; private MaterialDialog mDeprecatedDialog; - private VersionInfo mVersionInfo = VersionInfo.getInstance(); + private VersionService mVersionService = VersionService.getInstance(); public VersionGuard(Activity activity) { mActivity = activity; } - public void checkDeprecateAndUpdate() { - mVersionInfo.readDeprecatedFromPrefIfNeeded(mActivity); - if (mVersionInfo.isCurrentVersionDeprecated()) { + public void checkForDeprecatesAndUpdates() { + mVersionService.readDeprecatedFromPrefIfNeeded(mActivity); + if (mVersionService.isCurrentVersionDeprecated()) { showDeprecatedDialogIfNeeded(); } else { - checkUpdateIfNeeded(); + checkForUpdatesIfNeeded(); } } - private void checkUpdateIfNeeded() { - if (mVersionInfo.getUpdateInfo() == null) { - mVersionInfo.setOnReceiveUpdateResultCallback(new VersionInfo.OnReceiveUpdateResultCallback() { - @Override - public void onReceive(UpdateChecker.UpdateInfo info, boolean isCurrentVersionDeprecated) { - mVersionInfo.setOnReceiveUpdateResultCallback(null); - if (isCurrentVersionDeprecated) { - showDeprecatedDialogIfNeeded(); - } else { - showUpdateInfoIfNeeded(info); + private void checkForUpdatesIfNeeded() { + mVersionService.checkForUpdatesIfNeededAndUsingWifi(mActivity) + .subscribe(new SimpleObserver() { + + @Override + public void onNext(@io.reactivex.annotations.NonNull VersionInfo versionInfo) { + if (mVersionService.isCurrentVersionDeprecated()) { + showDeprecatedDialogIfNeeded(); + } else { + showUpdateInfoIfNeeded(versionInfo); + } } - } - }); - mVersionInfo.checkUpdateIfNeeded(mActivity); - } + + }); } - private void showUpdateInfoIfNeeded(UpdateChecker.UpdateInfo info) { + private void showUpdateInfoIfNeeded(com.stardust.scriptdroid.network.entity.VersionInfo info) { if (BuildConfig.VERSION_CODE < info.versionCode) { new UpdateInfoDialogBuilder(mActivity, info) .showDoNotAskAgain() @@ -64,7 +65,7 @@ public class VersionGuard { if (mDeprecatedDialog != null && mDeprecatedDialog.isShowing()) return; String content = mActivity.getString(R.string.warning_version_too_old); - String issues = mVersionInfo.getCurrentVersionIssues(); + String issues = mVersionService.getCurrentVersionIssues(); if (issues != null) { content += "\n" + issues; } @@ -79,8 +80,7 @@ public class VersionGuard { @Override public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) { if (which == DialogAction.POSITIVE) { - new UpdateCheckDialog(mActivity) - .show(); + VersionService.getInstance().checkForUpdatesAndShow(mActivity); } else { mActivity.finish(); } diff --git a/app/src/main/java/com/stardust/widget/EWebView.java b/app/src/main/java/com/stardust/widget/EWebView.java index e56f17e4..e5b36b46 100644 --- a/app/src/main/java/com/stardust/widget/EWebView.java +++ b/app/src/main/java/com/stardust/widget/EWebView.java @@ -1,5 +1,6 @@ package com.stardust.widget; +import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Bitmap; import android.os.Build; @@ -53,7 +54,7 @@ public class EWebView extends FrameLayout implements SwipeRefreshLayout.OnRefres settings.setUseWideViewPort(true); settings.setBuiltInZoomControls(true); settings.setLoadWithOverviewMode(true); - //settings.setJavaScriptEnabled(true); + settings.setJavaScriptEnabled(true); mWebView.setWebViewClient(new MyWebViewClient()); mWebView.setWebChromeClient(new MyWebChromeClient()); } diff --git a/app/src/main/java/com/stardust/widget/PrefSwitch.java b/app/src/main/java/com/stardust/widget/PrefSwitch.java index 6ba106aa..e11269b4 100644 --- a/app/src/main/java/com/stardust/widget/PrefSwitch.java +++ b/app/src/main/java/com/stardust/widget/PrefSwitch.java @@ -3,16 +3,11 @@ package com.stardust.widget; import android.content.Context; import android.content.SharedPreferences; import android.content.res.TypedArray; -import android.graphics.Paint; import android.preference.PreferenceManager; -import android.support.v7.widget.SwitchCompat; import android.util.AttributeSet; -import android.widget.CompoundButton; import com.stardust.scriptdroid.R; -import java.util.Objects; - /** * Created by Stardust on 2017/8/6. */ @@ -38,21 +33,21 @@ public class PrefSwitch extends SwitchCompat implements SharedPreferences.OnShar } private void init(AttributeSet attrs) { - mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(getContext()); - if (attrs != null) { - TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.PrefSwitch); - mPrefKey = a.getString(R.styleable.PrefSwitch_key); - boolean defaultValue = a.getBoolean(R.styleable.PrefSwitch_defaultValue, false); - if (mPrefKey != null) - setChecked(mSharedPreferences.getBoolean(mPrefKey, defaultValue), false); - else - setChecked(defaultValue, false); - a.recycle(); + if (attrs == null) + return; + TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.PrefSwitch); + mPrefKey = a.getString(R.styleable.PrefSwitch_key); + boolean defaultValue = a.getBoolean(R.styleable.PrefSwitch_defaultValue, false); + if (mPrefKey != null) { + mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(getContext()); + mSharedPreferences.registerOnSharedPreferenceChangeListener(this); + setChecked(mSharedPreferences.getBoolean(mPrefKey, defaultValue), false); + } else { + setChecked(defaultValue, false); } - mSharedPreferences.registerOnSharedPreferenceChangeListener(this); + a.recycle(); } - private void notifyPrefChanged(boolean isChecked) { if (mPrefKey == null) return; @@ -61,6 +56,13 @@ public class PrefSwitch extends SwitchCompat implements SharedPreferences.OnShar .apply(); } + public void setPrefKey(String prefKey) { + mPrefKey = prefKey; + if (mSharedPreferences == null) { + mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(getContext()); + mSharedPreferences.registerOnSharedPreferenceChangeListener(this); + } + } @Override public void setChecked(boolean checked) { diff --git a/app/src/main/java/com/stardust/widget/SwitchCompat.java b/app/src/main/java/com/stardust/widget/SwitchCompat.java new file mode 100644 index 00000000..f217a46f --- /dev/null +++ b/app/src/main/java/com/stardust/widget/SwitchCompat.java @@ -0,0 +1,50 @@ +package com.stardust.widget; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.CompoundButton; + +/** + * Created by Stardust on 2017/9/18. + */ + +public class SwitchCompat extends android.support.v7.widget.SwitchCompat { + + private boolean mIgnoreCheckedChange = false; + + public SwitchCompat(Context context) { + super(context); + } + + public SwitchCompat(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public SwitchCompat(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + + @Override + public void setOnCheckedChangeListener(final OnCheckedChangeListener listener) { + super.setOnCheckedChangeListener(new OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if (mIgnoreCheckedChange) { + return; + } + listener.onCheckedChanged(buttonView, isChecked); + } + }); + } + + public void setChecked(boolean checked, boolean notify) { + mIgnoreCheckedChange = !notify; + setChecked(checked); + mIgnoreCheckedChange = false; + } + + public void toggle(boolean notify) { + setChecked(!isChecked(), notify); + } +} diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index d03e0e7b..dbe986e8 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -49,6 +49,7 @@ android:layout_margin="16dp" android:clickable="true" android:src="@drawable/ic_add_white_48dp" + app:backgroundTint="@color/colorPrimary" app:layout_anchor="@id/viewpager" app:layout_anchorGravity="bottom|right|end" app:layout_behavior="com.stardust.widget.ScrollAwareFABBehavior"/> diff --git a/app/src/main/res/layout/drawer_menu.xml b/app/src/main/res/layout/drawer_menu.xml index 57ca4b31..1157d299 100644 --- a/app/src/main/res/layout/drawer_menu.xml +++ b/app/src/main/res/layout/drawer_menu.xml @@ -21,6 +21,7 @@ android:id="@+id/accessibility_service" android:layout_width="match_parent" android:layout_height="wrap_content" + app:anti_shake="true" app:icon="@drawable/ic_service_green" app:title="@string/text_accessibility_service" app:with_switch="true"/> @@ -30,6 +31,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" app:icon="@drawable/ic_stable" + app:pref_key="@string/key_stable_mode" app:title="@string/text_stable_mode" app:with_switch="true"/> @@ -46,6 +48,7 @@ android:id="@+id/floating_window" android:layout_width="match_parent" android:layout_height="wrap_content" + app:anti_shake="true" app:icon="@drawable/ic_robot_64" app:title="@string/text_floating_window" app:with_switch="true"/> @@ -55,6 +58,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" app:icon="@drawable/ic_volume" + app:pref_key="@string/key_use_volume_control_record" app:title="@string/text_volume_down_control" app:with_switch="true"/> @@ -71,6 +75,7 @@ android:id="@+id/debug" android:layout_width="match_parent" android:layout_height="wrap_content" + app:anti_shake="true" app:icon="@drawable/ic_debug" app:title="@string/debug" app:with_switch="true"/> diff --git a/app/src/main/res/layout/drawer_menu_item.xml b/app/src/main/res/layout/drawer_menu_item.xml index f00d4ac0..f8b26ee8 100644 --- a/app/src/main/res/layout/drawer_menu_item.xml +++ b/app/src/main/res/layout/drawer_menu_item.xml @@ -1,18 +1,33 @@ - + android:layout_margin="16dp"> + + + + + + + - diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index 1899cd1f..e71abde5 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -19,6 +19,8 @@ + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7158f5d6..8d6e77a5 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -236,11 +236,13 @@ 未登录 音量下键控制 其他 - 导入... + 导入… auto模式 ui模式 新建 选择文件 + 您的操作太快啦ヽ(#`Д´)ノ + 连接中… diff --git a/app/src/main/res/values/theme_colors.xml b/app/src/main/res/values/theme_colors.xml new file mode 100644 index 00000000..aecb3619 --- /dev/null +++ b/app/src/main/res/values/theme_colors.xml @@ -0,0 +1,43 @@ + + + 基佬红 + 基佬粉 + 基佬紫 + 基深紫 + 基靛蓝 + 基佬蓝 + 基亮蓝 + 基蓝绿 + 基佬青 + 基佬绿 + 基亮绿 + 基黄绿 + 基佬黄 + 基琥珀 + 基佬橙 + 基深橙 + 基佬棕 + 基佬灰 + 基蓝灰 + + + #F44336 + #E91E63 + #9C27B0 + #673AB7 + #3F51B5 + #2196F3 + #03A9F4 + #00BCD4 + #009688 + #4CAF50 + #8BC34A + #CDDC39 + #FFEB3B + #FFC107 + #FF9800 + #FF5722 + #795548 + #9E9E9E + #607D8B + \ No newline at end of file diff --git a/version.json b/version.json index 70ce9ed8..c525e79a 100644 --- a/version.json +++ b/version.json @@ -10,7 +10,7 @@ { "name": "百度手机助手", "url": "http://shouji.baidu.com/software/22060055.html" - }, + } ], "oldVersions": [ {