Init
This commit is contained in:
commit
52209017a3
198 files changed
+25167
No files matched your search
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import com.hippo.ehviewer.client.EhClient;
|
||||
import com.hippo.ehviewer.client.EhCookieStore;
|
||||
import com.hippo.network.StatusCodeException;
|
||||
import com.hippo.okhttp.CookieDB;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import okhttp3.OkHttpClient;
|
||||
|
||||
public class EhApplication extends Application {
|
||||
|
||||
private EhCookieStore mEhCookieStore;
|
||||
private EhClient mEhClient;
|
||||
private OkHttpClient mOkHttpClient;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
GetText.initialize(this);
|
||||
CookieDB.initialize(this);
|
||||
StatusCodeException.initialize(this);
|
||||
Settings.initialize(this);
|
||||
}
|
||||
|
||||
public static EhCookieStore getEhCookieStore(@NonNull Context context) {
|
||||
EhApplication application = ((EhApplication) context.getApplicationContext());
|
||||
if (application.mEhCookieStore == null) {
|
||||
application.mEhCookieStore = new EhCookieStore();
|
||||
}
|
||||
return application.mEhCookieStore;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static EhClient getEhClient(@NonNull Context context) {
|
||||
EhApplication application = ((EhApplication) context.getApplicationContext());
|
||||
if (application.mEhClient == null) {
|
||||
application.mEhClient = new EhClient(application);
|
||||
}
|
||||
return application.mEhClient;
|
||||
}
|
||||
|
||||
public static OkHttpClient getOkHttpClient(@NonNull Context context) {
|
||||
EhApplication application = ((EhApplication) context.getApplicationContext());
|
||||
if (application.mOkHttpClient == null) {
|
||||
application.mOkHttpClient = new OkHttpClient.Builder()
|
||||
.connectTimeout(15, TimeUnit.SECONDS)
|
||||
.readTimeout(15, TimeUnit.SECONDS)
|
||||
.writeTimeout(15, TimeUnit.SECONDS)
|
||||
.cookieJar(getEhCookieStore(application))
|
||||
.build();
|
||||
}
|
||||
return application.mOkHttpClient;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.StringRes;
|
||||
|
||||
public class GetText {
|
||||
|
||||
private static Resources sResources;
|
||||
|
||||
public static void initialize(Context context) {
|
||||
sResources = context.getApplicationContext().getResources();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static String getString(@StringRes int id) {
|
||||
return sResources.getString(id);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static String getString(@StringRes int id, Object... formatArgs) {
|
||||
return sResources.getString(id, formatArgs);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import com.hippo.yorozuya.NumberUtils;
|
||||
|
||||
public class Settings {
|
||||
|
||||
private static Context sContext;
|
||||
private static SharedPreferences sSettingsPre;
|
||||
|
||||
public static void initialize(Context context) {
|
||||
sContext = context.getApplicationContext();
|
||||
sSettingsPre = PreferenceManager.getDefaultSharedPreferences(sContext);
|
||||
}
|
||||
|
||||
public static boolean getBoolean(String key, boolean defValue) {
|
||||
return sSettingsPre.getBoolean(key, defValue);
|
||||
}
|
||||
|
||||
public static void putBoolean(String key, boolean value) {
|
||||
sSettingsPre.edit().putBoolean(key, value).apply();
|
||||
}
|
||||
|
||||
public static int getInt(String key, int defValue) {
|
||||
return sSettingsPre.getInt(key, defValue);
|
||||
}
|
||||
|
||||
public static void putInt(String key, int value) {
|
||||
sSettingsPre.edit().putInt(key, value).apply();
|
||||
}
|
||||
|
||||
public static long getLong(String key, long defValue) {
|
||||
return sSettingsPre.getLong(key, defValue);
|
||||
}
|
||||
|
||||
public static void putLong(String key, long value) {
|
||||
sSettingsPre.edit().putLong(key, value).apply();
|
||||
}
|
||||
|
||||
public static float getFloat(String key, float defValue) {
|
||||
return sSettingsPre.getFloat(key, defValue);
|
||||
}
|
||||
|
||||
public static void putFloat(String key, float value) {
|
||||
sSettingsPre.edit().putFloat(key, value).apply();
|
||||
}
|
||||
|
||||
public static String getString(String key, String defValue) {
|
||||
return sSettingsPre.getString(key, defValue);
|
||||
}
|
||||
|
||||
public static void putString(String key, String value) {
|
||||
sSettingsPre.edit().putString(key, value).apply();
|
||||
}
|
||||
|
||||
public static int getIntFromStr(String key, int defValue) {
|
||||
return NumberUtils.parseIntSafely(sSettingsPre.getString(key, Integer.toString(defValue)), defValue);
|
||||
}
|
||||
|
||||
public static void putIntToStr(String key, int value) {
|
||||
sSettingsPre.edit().putString(key, Integer.toString(value)).apply();
|
||||
}
|
||||
|
||||
private static final String KEY_DISPLAY_NAME = "display_name";
|
||||
private static final String DEFAULT_DISPLAY_NAME = null;
|
||||
|
||||
public static String getDisplayName() {
|
||||
return getString(KEY_DISPLAY_NAME, DEFAULT_DISPLAY_NAME);
|
||||
}
|
||||
|
||||
public static void putDisplayName(String value) {
|
||||
putString(KEY_DISPLAY_NAME, value);
|
||||
}
|
||||
|
||||
private static final String KEY_SHOW_WARNING = "show_warning";
|
||||
private static final boolean DEFAULT_SHOW_WARNING = true;
|
||||
|
||||
public static boolean getShowWarning() {
|
||||
return getBoolean(KEY_SHOW_WARNING, DEFAULT_SHOW_WARNING);
|
||||
}
|
||||
|
||||
public static void putShowWarning(boolean value) {
|
||||
putBoolean(KEY_SHOW_WARNING, value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.client;
|
||||
|
||||
public class CancelledException extends Exception {
|
||||
|
||||
public CancelledException() {
|
||||
super("CANCELED");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.client;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import com.hippo.ehviewer.EhApplication;
|
||||
import com.hippo.yorozuya.PriorityThreadFactory;
|
||||
import com.hippo.yorozuya.SimpleHandler;
|
||||
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import okhttp3.Call;
|
||||
import okhttp3.OkHttpClient;
|
||||
|
||||
public class EhClient {
|
||||
|
||||
public static final String TAG = EhClient.class.getSimpleName();
|
||||
|
||||
public static final int METHOD_SIGN_IN = 0;
|
||||
|
||||
private final ThreadPoolExecutor mRequestThreadPool;
|
||||
private final OkHttpClient mOkHttpClient;
|
||||
|
||||
public EhClient(Context context) {
|
||||
int poolSize = 3;
|
||||
BlockingQueue<Runnable> requestWorkQueue = new LinkedBlockingQueue<>();
|
||||
ThreadFactory threadFactory = new PriorityThreadFactory(TAG,
|
||||
android.os.Process.THREAD_PRIORITY_BACKGROUND);
|
||||
mRequestThreadPool = new ThreadPoolExecutor(poolSize, poolSize,
|
||||
1L, TimeUnit.SECONDS, requestWorkQueue, threadFactory);
|
||||
mOkHttpClient = EhApplication.getOkHttpClient(context);
|
||||
}
|
||||
|
||||
public void execute(EhRequest request) {
|
||||
if (!request.isCancelled()) {
|
||||
Task task = new Task(request.method, request.callback);
|
||||
task.executeOnExecutor(mRequestThreadPool, request.args);
|
||||
request.task = task;
|
||||
} else {
|
||||
request.callback.onCancel();
|
||||
}
|
||||
}
|
||||
|
||||
public class Task extends AsyncTask<Object, Void, Object> {
|
||||
|
||||
private int mMethod;
|
||||
private Callback mCallback;
|
||||
|
||||
private Call mCall;
|
||||
private boolean mStop;
|
||||
|
||||
public Task(int method, Callback callback) {
|
||||
mMethod = method;
|
||||
mCallback = callback;
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
if (!mStop) {
|
||||
mStop = true;
|
||||
|
||||
if (mCallback != null) {
|
||||
final Callback finalCallback = mCallback;
|
||||
SimpleHandler.getInstance().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
finalCallback.onCancel();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Status status = getStatus();
|
||||
if (status == Status.PENDING) {
|
||||
cancel(false);
|
||||
} else if (status == Status.RUNNING) {
|
||||
if (mCall != null) {
|
||||
mCall.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
// Clear
|
||||
mCall = null;
|
||||
mCallback = null;
|
||||
}
|
||||
}
|
||||
|
||||
private Object signIn(Object... params) throws Exception {
|
||||
Call call = EhEngine.prepareSignIn(mOkHttpClient, (String) params[0], (String) params[1]);
|
||||
if (!mStop) {
|
||||
mCall = call;
|
||||
return EhEngine.doSignIn(call);
|
||||
} else {
|
||||
throw new CancelledException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object doInBackground(Object... params) {
|
||||
try {
|
||||
switch (mMethod) {
|
||||
case METHOD_SIGN_IN:
|
||||
return signIn(params);
|
||||
default:
|
||||
return new IllegalStateException("Can't detect method " + mMethod);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected void onPostExecute(Object result) {
|
||||
if (mCallback != null) {
|
||||
//noinspection StatementWithEmptyBody
|
||||
if (!(result instanceof CancelledException)) {
|
||||
if (result instanceof Exception) {
|
||||
mCallback.onFailure((Exception) result);
|
||||
} else {
|
||||
mCallback.onSuccess(result);
|
||||
}
|
||||
} else {
|
||||
// onCancel is called in stop
|
||||
}
|
||||
}
|
||||
|
||||
// Clear
|
||||
mCall = null;
|
||||
mCallback = null;
|
||||
}
|
||||
}
|
||||
|
||||
public interface Callback<E> {
|
||||
|
||||
void onSuccess(E result);
|
||||
|
||||
void onFailure(Exception e);
|
||||
|
||||
void onCancel();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,665 @@
|
||||
/*
|
||||
* Copyright 2015 Hippo Seven
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.client;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
/**
|
||||
* Some configurable stuff about EH. It ends up cookie.
|
||||
*/
|
||||
public class EhConfig implements Cloneable {
|
||||
|
||||
/**
|
||||
* The Cookie key of uconfig
|
||||
*/
|
||||
public static final String KEY_UCONFIG = "uconfig";
|
||||
|
||||
/**
|
||||
* The key of load images through the Hentai@Home Network
|
||||
*/
|
||||
private static final String KEY_LOAD_FROM_HAH = "uh";
|
||||
/**
|
||||
* The key of scale images width
|
||||
*/
|
||||
private static final String KEY_SCALE_WIDTH = "rx";
|
||||
/**
|
||||
* The key of scale images height
|
||||
*/
|
||||
private static final String KEY_SCALE_HEIGHT = "ry";
|
||||
/**
|
||||
* The key of the behavior for downloading archiver
|
||||
*/
|
||||
private static final String KEY_ARCHIVER_DOWNLOAD = "ar";
|
||||
/**
|
||||
* The key of display mode would you like to use on the front and search pages
|
||||
*/
|
||||
private static final String KEY_LAYOUT_MODE = "dm";
|
||||
/**
|
||||
* The key of categories would you like to view as default on the front page
|
||||
*/
|
||||
private static final String KEY_DEFAULT_CATEGORIES = "cats";
|
||||
/**
|
||||
* The key of exclude certain namespaces from a default tag search
|
||||
*/
|
||||
private static final String KEY_EXCLUDED_NAMESPACES = "xns";
|
||||
/**
|
||||
* The key of hide galleries in certain languages from the gallery list and searches
|
||||
*/
|
||||
private static final String KEY_EXCLUDED_LANGUAGES = "xl";
|
||||
/**
|
||||
* The key of how many results would you like per page for the index/search page and torrent search pages
|
||||
*/
|
||||
private static final String KEY_RESULT_COUNT = "rc";
|
||||
/**
|
||||
* The key of mouse-over thumb
|
||||
*/
|
||||
private static final String KEY_MOUSE_OVER = "tl";
|
||||
/**
|
||||
* The key of preview size
|
||||
*/
|
||||
private static final String KEY_PREVIEW_SIZE = "ts";
|
||||
/**
|
||||
* The key of preview row per page
|
||||
*/
|
||||
private static final String KEY_PREVIEW_ROW = "tr";
|
||||
/**
|
||||
* The key of sort order for gallery comments
|
||||
*/
|
||||
private static final String KEY_COMMENTS_SORT = "cs";
|
||||
/**
|
||||
* The key of show gallery comment votes
|
||||
*/
|
||||
private static final String KEY_COMMENTS_VOTES = "sc";
|
||||
/**
|
||||
* The key of sort order for gallery tags
|
||||
*/
|
||||
private static final String KEY_TAGS_SORT = "to";
|
||||
/**
|
||||
* The key of show gallery page numbers
|
||||
*/
|
||||
private static final String KEY_SHOW_GALLERY_INDEX = "pn";
|
||||
/**
|
||||
* The key of the IP:Port of a proxy-enabled Hentai@Home Client
|
||||
* to load all images
|
||||
*/
|
||||
private static final String KEY_HAH_CLIENT_IP_PORT = "hp";
|
||||
/**
|
||||
* The key of the passkey of a proxy-enabled Hentai@Home Client
|
||||
* to load all images
|
||||
*/
|
||||
private static final String KEY_HAH_CLIENT_PASSKEY = "hk";
|
||||
/**
|
||||
* The key of enable Tag Flagging
|
||||
*/
|
||||
private static final String KEY_ENABLE_TAG_FLAGGING = "tf";
|
||||
/**
|
||||
* The key of always display the original images instead of the resampled versions
|
||||
*/
|
||||
private static final String KEY_ALWAYS_ORIGINAL = "oi";
|
||||
/**
|
||||
* The key of enable the multi-Page Viewer
|
||||
*/
|
||||
private static final String KEY_MULTI_PAGE = "qb";
|
||||
/**
|
||||
* The key of multi-Page Viewer Display Style
|
||||
*/
|
||||
private static final String KEY_MULTI_PAGE_STYLE = "ms";
|
||||
/**
|
||||
* The key of multi-Page Viewer Thumbnail Pane
|
||||
*/
|
||||
private static final String KEY_MULTI_PAGE_THUMB = "mt";
|
||||
|
||||
/**
|
||||
* The Cookie key of lofi resolution
|
||||
*/
|
||||
public static final String KEY_LOFI_RESOLUTION = "xres";
|
||||
|
||||
/**
|
||||
* The Cookie key of show warning
|
||||
*/
|
||||
public static final String KEY_CONTENT_WARNING = "nw";
|
||||
|
||||
/**
|
||||
* load images through the Hentai@Home Network
|
||||
*/
|
||||
public static final String LOAD_FROM_HAH_YES = "y";
|
||||
/**
|
||||
* do not load images through the Hentai@Home Network
|
||||
*/
|
||||
public static final String LOAD_FROM_HAH_NO = "n";
|
||||
|
||||
/**
|
||||
* Manual Accept, Manual Start
|
||||
*/
|
||||
public static final String ARCHIVER_DOWNLOAD_MAMS = "0";
|
||||
/**
|
||||
* >Manual Accept, Auto Start
|
||||
*/
|
||||
public static final String ARCHIVER_DOWNLOAD_AAMS = "1";
|
||||
/**
|
||||
* Auto Accept, Manual Start
|
||||
*/
|
||||
public static final String ARCHIVER_DOWNLOAD_MAAS = "2";
|
||||
/**
|
||||
* Auto Accept, Auto Start
|
||||
*/
|
||||
public static final String ARCHIVER_DOWNLOAD_AAAS = "3";
|
||||
|
||||
/**
|
||||
* List View on the front and search pages
|
||||
*/
|
||||
public static final String LAYOUT_MODE_LIST = "l";
|
||||
/**
|
||||
* Thumbnail View on the front and search pages
|
||||
*/
|
||||
public static final String LAYOUT_MODE_THUMB = "t";
|
||||
|
||||
public static final int MISC = 0x1;
|
||||
public static final int DOUJINSHI = 0x2;
|
||||
public static final int MANGA = 0x4;
|
||||
public static final int ARTIST_CG = 0x8;
|
||||
public static final int GAME_CG = 0x10;
|
||||
public static final int IMAGE_SET = 0x20;
|
||||
public static final int COSPLAY = 0x40;
|
||||
public static final int ASIAN_PORN = 0x80;
|
||||
public static final int NON_H = 0x100;
|
||||
public static final int WESTERN = 0x200;
|
||||
|
||||
public static final int NAMESPACES_RECLASS = 0x1;
|
||||
public static final int NAMESPACES_LANGUAGE = 0x2;
|
||||
public static final int NAMESPACES_PARODY = 0x4;
|
||||
public static final int NAMESPACES_CHARACTER = 0x8;
|
||||
public static final int NAMESPACES_GROUP = 0x10;
|
||||
public static final int NAMESPACES_ARTIST = 0x20;
|
||||
public static final int NAMESPACES_MALE = 0x40;
|
||||
public static final int NAMESPACES_FEMALE = 0x80;
|
||||
|
||||
public static final String JAPANESE_TRANSLATED = "1024";
|
||||
public static final String JAPANESE_REWRITE = "2048";
|
||||
public static final String ENGLISH_ORIGINAL = "1";
|
||||
public static final String ENGLISH_TRANSLATED = "1025";
|
||||
public static final String ENGLISH_REWRITE = "2049";
|
||||
public static final String CHINESE_ORIGINAL = "10";
|
||||
public static final String CHINESE_TRANSLATED = "1034";
|
||||
public static final String CHINESE_REWRITE = "2058";
|
||||
public static final String DUTCH_ORIGINAL = "20";
|
||||
public static final String DUTCH_TRANSLATED = "1044";
|
||||
public static final String DUTCH_REWRITE = "2068";
|
||||
public static final String FRENCH_ORIGINAL = "30";
|
||||
public static final String FRENCH_TRANSLATED = "1054";
|
||||
public static final String FRENCH_REWRITE = "2078";
|
||||
public static final String GERMAN_ORIGINAL = "40";
|
||||
public static final String GERMAN_TRANSLATED = "1064";
|
||||
public static final String GERMAN_REWRITE = "2088";
|
||||
public static final String HUNGARIAN_ORIGINAL = "50";
|
||||
public static final String HUNGARIAN_TRANSLATED = "1074";
|
||||
public static final String HUNGARIAN_REWRITE = "2098";
|
||||
public static final String ITALIAN_ORIGINAL = "60";
|
||||
public static final String ITALIAN_TRANSLATED = "1084";
|
||||
public static final String ITALIAN_REWRITE = "2108";
|
||||
public static final String KOREAN_ORIGINAL = "70";
|
||||
public static final String KOREAN_TRANSLATED = "1094";
|
||||
public static final String KOREAN_REWRITE = "2118";
|
||||
public static final String POLISH_ORIGINAL = "80";
|
||||
public static final String POLISH_TRANSLATED = "1104";
|
||||
public static final String POLISH_REWRITE = "2128";
|
||||
public static final String PORTUGUESE_ORIGINAL = "90";
|
||||
public static final String PORTUGUESE_TRANSLATED = "1114";
|
||||
public static final String PORTUGUESE_REWRITE = "2138";
|
||||
public static final String RUSSIAN_ORIGINAL = "100";
|
||||
public static final String RUSSIAN_TRANSLATED = "1124";
|
||||
public static final String RUSSIAN_REWRITE = "2148";
|
||||
public static final String SPANISH_ORIGINAL = "110";
|
||||
public static final String SPANISH_TRANSLATED = "1134";
|
||||
public static final String SPANISH_REWRITE = "2158";
|
||||
public static final String THAI_ORIGINAL = "120";
|
||||
public static final String THAI_TRANSLATED = "1144";
|
||||
public static final String THAI_REWRITE = "2168";
|
||||
public static final String VIETNAMESE_ORIGINAL = "130";
|
||||
public static final String VIETNAMESE_TRANSLATED = "1154";
|
||||
public static final String VIETNAMESE_REWRITE = "2178";
|
||||
public static final String NA_ORIGINAL = "254";
|
||||
public static final String NA_TRANSLATED = "1278";
|
||||
public static final String NA_REWRITE = "2302";
|
||||
public static final String OTHER_ORIGINAL = "255";
|
||||
public static final String OTHER_TRANSLATED = "1279";
|
||||
public static final String OTHER_REWRITE = "2303";
|
||||
|
||||
/**
|
||||
* 25 results per page for the index/search page and torrent search pages
|
||||
*/
|
||||
public static final String RESULT_COUNT_25 = "0";
|
||||
/**
|
||||
* 50 results per page for the index/search page and torrent search pages
|
||||
*/
|
||||
public static final String RESULT_COUNT_50 = "1";
|
||||
/**
|
||||
* 100 results per page for the index/search page and torrent search pages
|
||||
*/
|
||||
public static final String RESULT_COUNT_100 = "2";
|
||||
/**
|
||||
* 200 results per page for the index/search page and torrent search pages
|
||||
*/
|
||||
public static final String RESULT_COUNT_200 = "3";
|
||||
|
||||
/**
|
||||
* On mouse-over
|
||||
*/
|
||||
public static final String MOUSE_OVER_YES = "m";
|
||||
/**
|
||||
* On page load
|
||||
*/
|
||||
public static final String MOUSE_OVER_NO = "p";
|
||||
|
||||
/**
|
||||
* Preview normal size
|
||||
*/
|
||||
public static final String PREVIEW_SIZE_NORMAL = "m";
|
||||
/**
|
||||
* Preview large size
|
||||
*/
|
||||
public static final String PREVIEW_SIZE_LARGE = "l";
|
||||
|
||||
/**
|
||||
* 4 row preview per page
|
||||
*/
|
||||
public static final String PREVIEW_ROW_4 = "2";
|
||||
/**
|
||||
* 10 row preview per page
|
||||
*/
|
||||
public static final String PREVIEW_ROW_10 = "5";
|
||||
/**
|
||||
* 20 row preview per page
|
||||
*/
|
||||
public static final String PREVIEW_ROW_20 = "10";
|
||||
/**
|
||||
* 40 row preview per page
|
||||
*/
|
||||
public static final String PREVIEW_ROW_40 = "20";
|
||||
|
||||
/**
|
||||
* Oldest comments first
|
||||
*/
|
||||
public static final String COMMENTS_SORT_OLDEST_FIRST = "a";
|
||||
/**
|
||||
* Recent comments first
|
||||
*/
|
||||
public static final String COMMENTS_SORT_RECENT_FIRST = "d";
|
||||
/**
|
||||
* By highest score
|
||||
*/
|
||||
public static final String COMMENTS_SORT_HIGHEST_SCORE_FIRST = "s";
|
||||
|
||||
/**
|
||||
* Show gallery comment votes On score hover or click
|
||||
*/
|
||||
public static final String COMMENTS_VOTES_POP = "0";
|
||||
/**
|
||||
* Always show gallery comment votes
|
||||
*/
|
||||
public static final String COMMENTS_VOTES_ALWAYS = "1";
|
||||
|
||||
/**
|
||||
* Sort order for gallery tags alphabetically
|
||||
*/
|
||||
public static final String TAGS_SORT_ALPHABETICAL = "a";
|
||||
/**
|
||||
* Sort order for gallery tags by tag power
|
||||
*/
|
||||
public static final String TAGS_SORT_POWER = "p";
|
||||
|
||||
/**
|
||||
* Show gallery page numbers
|
||||
*/
|
||||
public static final String SHOW_GALLERY_INDEX_YES = "1";
|
||||
/**
|
||||
* Do not show gallery page numbers
|
||||
*/
|
||||
public static final String SHOW_GALLERY_INDEX_NO = "0";
|
||||
|
||||
/**
|
||||
* Enable Tag Flagging
|
||||
*/
|
||||
public static final String ENABLE_TAG_FLAGGING_YES = "y";
|
||||
/**
|
||||
* Do not enable Tag Flagging
|
||||
*/
|
||||
public static final String ENABLE_TAG_FLAGGING_NO = "n";
|
||||
|
||||
/**
|
||||
* Always display the original images
|
||||
*/
|
||||
public static final String ALWAYS_ORIGINAL_YES = "y";
|
||||
/**
|
||||
* Do not Always display the original images
|
||||
*/
|
||||
public static final String ALWAYS_ORIGINAL_NO = "n";
|
||||
|
||||
/**
|
||||
* Enable the Multi-Page Viewe
|
||||
*/
|
||||
public static final String MULTI_PAGE_YES = "y";
|
||||
/**
|
||||
* Do not enable the Multi-Page Viewe
|
||||
*/
|
||||
public static final String MULTI_PAGE_NO = "n";
|
||||
|
||||
/**
|
||||
* Align left, only scale if image is larger than browser width
|
||||
*/
|
||||
public static final String MULTI_PAGE_STYLE_N = "n";
|
||||
/**
|
||||
* Align center, only scale if image is larger than browser width
|
||||
*/
|
||||
public static final String MULTI_PAGE_STYLE_C = "c";
|
||||
/**
|
||||
* Align center, Always scale images to fit browser width
|
||||
*/
|
||||
public static final String MULTI_PAGE_STYLE_Y = "y";
|
||||
|
||||
/**
|
||||
* Show Multi-Page Viewer Thumbnail Pane
|
||||
*/
|
||||
public static final String MULTI_PAGE_THUMB_SHOW = "n";
|
||||
/**
|
||||
* Hide Multi-Page Viewer Thumbnail Pane
|
||||
*/
|
||||
public static final String MULTI_PAGE_THUMB_HIDE = "y";
|
||||
|
||||
/**
|
||||
* 460x for lofi resolution
|
||||
*/
|
||||
public static final String LOFI_RESOLUTION_460X = "1";
|
||||
|
||||
/**
|
||||
* 780X for lofi resolution
|
||||
*/
|
||||
public static final String LOFI_RESOLUTION_780X = "2";
|
||||
|
||||
/**
|
||||
* 980X for lofi resolution
|
||||
*/
|
||||
public static final String LOFI_RESOLUTION_980X = "3";
|
||||
|
||||
/**
|
||||
* show warning
|
||||
*/
|
||||
private static final String CONTENT_WARNING_SHOW = "0";
|
||||
|
||||
/**
|
||||
* not show warning
|
||||
*/
|
||||
private static final String CONTENT_WARNING_NOT_SHOW = "1";
|
||||
|
||||
/**
|
||||
* Load images through the Hentai@Home Network<br/>
|
||||
* key: {@link #KEY_LOAD_FROM_HAH}<br/>
|
||||
* value: {@link #LOAD_FROM_HAH_YES}, {@link #LOAD_FROM_HAH_NO}
|
||||
*/
|
||||
public String loadFromHAH = LOAD_FROM_HAH_YES;
|
||||
|
||||
/**
|
||||
* Scale width<br/>
|
||||
* key: {@link #KEY_SCALE_WIDTH}<br/>
|
||||
* value: 0 for no limit
|
||||
*/
|
||||
public int scaleWidth = 0;
|
||||
|
||||
/**
|
||||
* Scale height<br/>
|
||||
* key: {@link #KEY_SCALE_HEIGHT}<br/>
|
||||
* value: 0 for no limit
|
||||
*/
|
||||
public int scaleHeight = 0;
|
||||
|
||||
/**
|
||||
* The default behavior for downloading an archiver<br/>
|
||||
* key: {@link #KEY_ARCHIVER_DOWNLOAD}<br/>
|
||||
* value: {@link #ARCHIVER_DOWNLOAD_MAMS}, {@link #ARCHIVER_DOWNLOAD_AAMS},
|
||||
* {@link #ARCHIVER_DOWNLOAD_MAAS}, {@link #ARCHIVER_DOWNLOAD_AAAS}
|
||||
*/
|
||||
public String archiverDownload = ARCHIVER_DOWNLOAD_MAMS;
|
||||
|
||||
/**
|
||||
* Display mode used on the front and search pages<br/>
|
||||
* false for list, true for thumb<br/>
|
||||
* key: {@link #KEY_LAYOUT_MODE}<br/>
|
||||
* value: {@link #LAYOUT_MODE_LIST}, {@link #LAYOUT_MODE_THUMB}
|
||||
*/
|
||||
public String layoutMode = LAYOUT_MODE_LIST;
|
||||
|
||||
/**
|
||||
* Default categories on the front page<br/>
|
||||
* key: {@link #KEY_DEFAULT_CATEGORIES}<br/>
|
||||
* value: the value of categories, for multiple use & operation,
|
||||
* 0 for none
|
||||
*/
|
||||
public int defaultCategories = 0;
|
||||
|
||||
/**
|
||||
* Certain namespaces excluded from a default tag search<br/>
|
||||
* key: {@link #KEY_EXCLUDED_NAMESPACES}<br/>
|
||||
* value: the value of namespaces, for multiple use & operation,
|
||||
* 0 for none
|
||||
*/
|
||||
public int excludedNamespaces = 0;
|
||||
|
||||
/**
|
||||
* Certain languages excluded from list and searches<br/>
|
||||
* key: {@link #KEY_EXCLUDED_LANGUAGES}<br/>
|
||||
* value: {@link #JAPANESE_TRANSLATED}, {@link #JAPANESE_REWRITE} ...
|
||||
* For multiple languages, use <code>x<code/> to combine them, like 1x1024x2048
|
||||
*/
|
||||
public String excludedLanguages = "";
|
||||
|
||||
/**
|
||||
* How many results would you like per page for the index/search page
|
||||
* and torrent search pages<br/>
|
||||
* key: {@link #KEY_RESULT_COUNT}<br/>
|
||||
* value: {@link #RESULT_COUNT_25}, {@link #RESULT_COUNT_50},
|
||||
* {@link #RESULT_COUNT_100}, {@link #RESULT_COUNT_200}<br/>
|
||||
* Require <code>Hath Perk:Paging Enlargement</code>
|
||||
*/
|
||||
public String resultCount = RESULT_COUNT_25;
|
||||
|
||||
/**
|
||||
* mouse-over thumb<br/>
|
||||
* key: {@link #KEY_MOUSE_OVER}<br/>
|
||||
* value: {@link #MOUSE_OVER_YES}, {@link #MOUSE_OVER_NO}
|
||||
*/
|
||||
public String mouseOver = MOUSE_OVER_YES;
|
||||
|
||||
/**
|
||||
* Default preview mode<br/>
|
||||
* key: {@link #KEY_PREVIEW_SIZE}<br/>
|
||||
* value: {@link #PREVIEW_SIZE_NORMAL}, {@link #PREVIEW_SIZE_LARGE}
|
||||
*/
|
||||
public String previewSize = PREVIEW_SIZE_NORMAL;
|
||||
|
||||
/**
|
||||
* Preview row<br/>
|
||||
* key: {@link #KEY_PREVIEW_ROW}<br/>
|
||||
* value: {@link #PREVIEW_ROW_4}, {@link #PREVIEW_ROW_10},
|
||||
* {@link #PREVIEW_ROW_20}, {@link #PREVIEW_ROW_40}
|
||||
*/
|
||||
public String previewRow = PREVIEW_ROW_4;
|
||||
|
||||
/**
|
||||
* Sort order for gallery comments<br/>
|
||||
* key: {@link #KEY_COMMENTS_SORT}<br/>
|
||||
* value: {@link #COMMENTS_SORT_OLDEST_FIRST}, {@link #COMMENTS_SORT_RECENT_FIRST},
|
||||
* {@link #COMMENTS_SORT_HIGHEST_SCORE_FIRST}
|
||||
*/
|
||||
public String commentSort = COMMENTS_SORT_OLDEST_FIRST;
|
||||
|
||||
/**
|
||||
* Show gallery comment votes mode<br/>
|
||||
* key: {@link #KEY_COMMENTS_VOTES}<br/>
|
||||
* value: {@link #COMMENTS_VOTES_POP}, {@link #COMMENTS_VOTES_ALWAYS}
|
||||
*/
|
||||
public String commentVotes = COMMENTS_VOTES_POP;
|
||||
|
||||
|
||||
/**
|
||||
* Sort order for gallery tags<br/>
|
||||
* key: {@link #KEY_TAGS_SORT}<br/>
|
||||
* value: {@link #TAGS_SORT_ALPHABETICAL}, {@link #TAGS_SORT_POWER}
|
||||
*/
|
||||
public String tagSort = TAGS_SORT_ALPHABETICAL;
|
||||
|
||||
/**
|
||||
* Show gallery page numbers<br/>
|
||||
* key: {@link #KEY_SHOW_GALLERY_INDEX}<br/>
|
||||
* value: {@link #SHOW_GALLERY_INDEX_YES}, {@link #SHOW_GALLERY_INDEX_NO}
|
||||
*/
|
||||
public String showGalleryIndex = SHOW_GALLERY_INDEX_YES;
|
||||
|
||||
/**
|
||||
* The IP of a proxy-enabled Hentai@Home Client
|
||||
* to load all images<br/>
|
||||
* key: {@link #KEY_HAH_CLIENT_IP_PORT}<br/>
|
||||
*/
|
||||
public String hahClientIp = "";
|
||||
|
||||
/**
|
||||
* The PORT of a proxy-enabled Hentai@Home Client
|
||||
* to load all images<br/>
|
||||
* key: {@link #KEY_HAH_CLIENT_IP_PORT}<br/>
|
||||
*/
|
||||
public int hahClientPort = -1;
|
||||
|
||||
/**
|
||||
* The passkey of a proxy-enabled Hentai@Home Client
|
||||
* to load all images<br/>
|
||||
* key: {@link #KEY_HAH_CLIENT_PASSKEY}<br/>
|
||||
*/
|
||||
public String hahClientPasskey = "";
|
||||
|
||||
/**
|
||||
* Enable tag flagging
|
||||
* key: {@link #KEY_ENABLE_TAG_FLAGGING}<br/>
|
||||
* value: {@link #ENABLE_TAG_FLAGGING_YES}, {@link #ENABLE_TAG_FLAGGING_NO}<br/>
|
||||
* <code>Bronze Star</code> or <code>Hath Perk: Tag Flagging</code> Required
|
||||
*/
|
||||
public String enableTagFlagging = ENABLE_TAG_FLAGGING_NO;
|
||||
|
||||
/**
|
||||
* Always display the original images instead of the resampled versions<br/>
|
||||
* key: {@link #KEY_ALWAYS_ORIGINAL}<br/>
|
||||
* value: {@link #ALWAYS_ORIGINAL_YES}, {@link #ALWAYS_ORIGINAL_NO}<br/>
|
||||
* <code>Silver Star</code> or <code>Hath Perk: Source Nexus</code> Required
|
||||
*/
|
||||
public String alwaysOriginal = ALWAYS_ORIGINAL_NO;
|
||||
|
||||
/**
|
||||
* Enable the multi-Page Viewer<br/>
|
||||
* key: {@link #KEY_MULTI_PAGE}<br/>
|
||||
* value: {@link #MULTI_PAGE_YES}, {@link #MULTI_PAGE_NO}<br/>
|
||||
* <code>Gold Star</code> or <code>Hath Perk: Multi-Page Viewer</code> Required
|
||||
*/
|
||||
public String multiPage = MULTI_PAGE_NO;
|
||||
|
||||
/**
|
||||
* Multi-Page Viewer Display Style<br/>
|
||||
* key: {@link #KEY_MULTI_PAGE_STYLE}<br/>
|
||||
* value: {@link #MULTI_PAGE_STYLE_N}, {@link #MULTI_PAGE_STYLE_C},
|
||||
* {@link #MULTI_PAGE_STYLE_Y}<br/>
|
||||
* <code>Gold Star</code> or <code>Hath Perk: Multi-Page Viewer</code> Required
|
||||
*/
|
||||
public String multiPageStyle = MULTI_PAGE_STYLE_N;
|
||||
|
||||
/**
|
||||
* Multi-Page Viewer Thumbnail Pane<br/>
|
||||
* key: {@link #KEY_MULTI_PAGE_THUMB}<br/>
|
||||
* value: {@link #MULTI_PAGE_THUMB_SHOW}, {@link #MULTI_PAGE_THUMB_HIDE}<br/>
|
||||
* <code>Gold Star</code> or <code>Hath Perk: Multi-Page Viewer</code> Required
|
||||
*/
|
||||
public String multiPageThumb = MULTI_PAGE_THUMB_SHOW;
|
||||
|
||||
/**
|
||||
* Lofi resolution
|
||||
* key: {@link #KEY_LOFI_RESOLUTION}<br/>
|
||||
* value: {@link #LOFI_RESOLUTION_460X}, {@link #LOFI_RESOLUTION_780X},
|
||||
* {@link #LOFI_RESOLUTION_980X}
|
||||
*/
|
||||
public String lofiResolution = LOFI_RESOLUTION_980X;
|
||||
|
||||
/**
|
||||
* Show content warning
|
||||
* key: {@link #KEY_CONTENT_WARNING}<br/>
|
||||
* value: {@link #CONTENT_WARNING_SHOW}, {@link #CONTENT_WARNING_NOT_SHOW}
|
||||
*/
|
||||
public String contentWarning = CONTENT_WARNING_NOT_SHOW;
|
||||
|
||||
private String mUconfig;
|
||||
|
||||
private boolean mDirty = true;
|
||||
|
||||
@Override
|
||||
public EhConfig clone() {
|
||||
try {
|
||||
return (EhConfig) super.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setDirty() {
|
||||
mDirty = true;
|
||||
}
|
||||
|
||||
private void updateUconfig() {
|
||||
String hahClientIpPort = (TextUtils.isEmpty(hahClientIp) || hahClientPort == -1) ?
|
||||
"" : hahClientIp + "%3A" + hahClientPort;
|
||||
mUconfig = KEY_LOAD_FROM_HAH + "_" + loadFromHAH + "-" +
|
||||
KEY_SCALE_WIDTH + "_" + scaleWidth + "-" +
|
||||
KEY_SCALE_HEIGHT + "_" + scaleHeight + "-" +
|
||||
KEY_ARCHIVER_DOWNLOAD + "_" + archiverDownload + "-" +
|
||||
KEY_LAYOUT_MODE + "_" + layoutMode + "-" +
|
||||
KEY_DEFAULT_CATEGORIES + "_" + defaultCategories + "-" +
|
||||
KEY_EXCLUDED_NAMESPACES + "_" + excludedNamespaces + "-" +
|
||||
KEY_EXCLUDED_LANGUAGES + "_" + excludedLanguages + "-" +
|
||||
KEY_RESULT_COUNT + "_" + resultCount + "-" +
|
||||
KEY_MOUSE_OVER + "_" + mouseOver + "-" +
|
||||
KEY_PREVIEW_SIZE + "_" + previewSize + "-" +
|
||||
KEY_PREVIEW_ROW + "_" + previewRow + "-" +
|
||||
KEY_COMMENTS_SORT + "_" + commentSort + "-" +
|
||||
KEY_COMMENTS_VOTES + "_" + commentVotes + "-" +
|
||||
KEY_TAGS_SORT + "_" + tagSort + "-" +
|
||||
KEY_SHOW_GALLERY_INDEX + "_" + showGalleryIndex + "-" +
|
||||
KEY_HAH_CLIENT_IP_PORT + "_" + hahClientIpPort + "-" +
|
||||
KEY_HAH_CLIENT_PASSKEY + "_" + hahClientPasskey + "-" +
|
||||
KEY_ENABLE_TAG_FLAGGING + "_" + enableTagFlagging + "-" +
|
||||
KEY_ALWAYS_ORIGINAL + "_" + alwaysOriginal + "-" +
|
||||
KEY_MULTI_PAGE + "_" + multiPage + "-" +
|
||||
KEY_MULTI_PAGE_STYLE + "_" + multiPageStyle + "-" +
|
||||
KEY_MULTI_PAGE_THUMB + "_" + multiPageThumb;
|
||||
}
|
||||
|
||||
/*
|
||||
public void fillCookie(Cookie cookie) {
|
||||
if (mDirty) {
|
||||
mDirty = false;
|
||||
updateUconfig();
|
||||
}
|
||||
|
||||
cookie.put(KEY_UCONFIG, mUconfig);
|
||||
cookie.put(KEY_LOFI_RESOLUTION, lofiResolution);
|
||||
cookie.put(KEY_CONTENT_WARNING, contentWarning);
|
||||
}
|
||||
*/
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.client;
|
||||
|
||||
import com.hippo.okhttp.CookieDB;
|
||||
import com.hippo.okhttp.CookieDBStore;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import okhttp3.Cookie;
|
||||
import okhttp3.HttpUrl;
|
||||
|
||||
public class EhCookieStore extends CookieDBStore {
|
||||
|
||||
private static final String KEY_IPD_MEMBER_ID = "ipb_member_id";
|
||||
private static final String KEY_IPD_PASS_HASH = "ipb_pass_hash";
|
||||
private static final String KEY_YAY = "yay";
|
||||
|
||||
public void cleanUpForSignIn() {
|
||||
remove(EhUrl.HOST_E, KEY_IPD_MEMBER_ID);
|
||||
remove(EhUrl.HOST_E, KEY_IPD_PASS_HASH);
|
||||
remove(EhUrl.HOST_EX, KEY_IPD_MEMBER_ID);
|
||||
remove(EhUrl.HOST_EX, KEY_IPD_PASS_HASH);
|
||||
remove(EhUrl.HOST_EX, KEY_YAY);
|
||||
}
|
||||
|
||||
public boolean hasSignedIn() {
|
||||
return contain(EhUrl.HOST_EX, KEY_IPD_MEMBER_ID) &&
|
||||
contain(EhUrl.HOST_EX, KEY_IPD_PASS_HASH);
|
||||
}
|
||||
|
||||
private Cookie newCookie(Cookie cookie, String newDomain) {
|
||||
Cookie.Builder builder = new Cookie.Builder();
|
||||
builder.name(cookie.name());
|
||||
builder.value(cookie.value());
|
||||
if (cookie.persistent()) {
|
||||
builder.expiresAt(cookie.expiresAt());
|
||||
}
|
||||
if (cookie.hostOnly()) {
|
||||
builder.hostOnlyDomain(newDomain);
|
||||
} else {
|
||||
builder.domain(newDomain);
|
||||
}
|
||||
builder.path(cookie.path());
|
||||
if (cookie.secure()) {
|
||||
builder.secure();
|
||||
}
|
||||
if (cookie.httpOnly()) {
|
||||
builder.httpOnly();
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
|
||||
List<Cookie> cs = new ArrayList<>(cookies.size() + 2);
|
||||
|
||||
for (Cookie cookie: cookies) {
|
||||
cs.add(cookie);
|
||||
if (EhUrl.HOST_E.equals(cookie.domain()) &&
|
||||
(KEY_IPD_MEMBER_ID.equals(cookie.name()) ||
|
||||
KEY_IPD_PASS_HASH.equals(cookie.name()))) {
|
||||
cs.add(newCookie(cookie, CookieDB.cookiesDomain(EhUrl.HOST_EX)));
|
||||
}
|
||||
}
|
||||
|
||||
super.saveFromResponse(url, cs);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.client;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.hippo.ehviewer.client.parser.SignInParser;
|
||||
import com.hippo.network.StatusCodeException;
|
||||
|
||||
import okhttp3.Call;
|
||||
import okhttp3.FormBody;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
|
||||
public class EhEngine {
|
||||
|
||||
private static final String TAG = EhEngine.class.getSimpleName();
|
||||
|
||||
public static final String UNKNOWN = "Unknown";
|
||||
|
||||
private static void throwException(Call call, int code, String body, Exception e) throws Exception {
|
||||
if (call.isCanceled()) {
|
||||
throw new CancelledException();
|
||||
}
|
||||
|
||||
if (e instanceof EhException) {
|
||||
if (!UNKNOWN.equals(e.getMessage())) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
if (!body.contains("<")) {
|
||||
throw new EhException(body);
|
||||
}
|
||||
|
||||
if (code >= 400) {
|
||||
throw new StatusCodeException(code);
|
||||
}
|
||||
}
|
||||
|
||||
public static Call prepareSignIn(OkHttpClient okHttpClient, String username, String password) {
|
||||
FormBody.Builder builder = new FormBody.Builder()
|
||||
.add("UserName", username)
|
||||
.add("PassWord", password)
|
||||
.add("submit", "Log me in")
|
||||
.add("CookieDate", "1")
|
||||
.add("temporary_https", "off");
|
||||
|
||||
String url = EhUrl.API_SIGN_IN;
|
||||
Log.d(TAG, url);
|
||||
Request request = new EhRequestBuilder(url)
|
||||
.post(builder.build())
|
||||
.build();
|
||||
return okHttpClient.newCall(request);
|
||||
}
|
||||
|
||||
public static String doSignIn(Call call) throws Exception {
|
||||
String body = null;
|
||||
int code = -1;
|
||||
try {
|
||||
Response response = call.execute();
|
||||
code = response.code();
|
||||
body = response.body().string();
|
||||
return SignInParser.parse(body);
|
||||
} catch (Exception e) {
|
||||
throwException(call, code, body, e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.client;
|
||||
|
||||
public class EhException extends Exception {
|
||||
|
||||
public EhException(String detailMessage) {
|
||||
super(detailMessage);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.client;
|
||||
|
||||
public class EhRequest {
|
||||
|
||||
int method;
|
||||
Object[] args;
|
||||
EhClient.Callback callback;
|
||||
|
||||
EhClient.Task task;
|
||||
|
||||
private boolean mCancel = false;
|
||||
|
||||
public EhRequest setMethod(int method) {
|
||||
this.method = method;
|
||||
return this;
|
||||
}
|
||||
|
||||
public EhRequest setArgs(Object... args) {
|
||||
this.args = args;
|
||||
return this;
|
||||
}
|
||||
|
||||
public EhRequest setCallback(EhClient.Callback callback) {
|
||||
this.callback = callback;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
if (!mCancel) {
|
||||
mCancel = true;
|
||||
if (task != null) {
|
||||
task.stop();
|
||||
task = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isCancelled() {
|
||||
return mCancel;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.client;
|
||||
|
||||
import com.hippo.okhttp.ChromeRequestBuilder;
|
||||
|
||||
public class EhRequestBuilder extends ChromeRequestBuilder {
|
||||
|
||||
public EhRequestBuilder(String url) {
|
||||
super(url);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.client;
|
||||
|
||||
public class EhUrl {
|
||||
|
||||
public static final String HOST_EX = "exhentai.org";
|
||||
public static final String HOST_E = "e-hentai.org";
|
||||
|
||||
public static final String API_SIGN_IN = "http://forums.e-hentai.org/index.php?act=Login&CODE=01";
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.client;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.hippo.ehviewer.EhApplication;
|
||||
import com.hippo.ehviewer.Settings;
|
||||
|
||||
public class EhUtils {
|
||||
|
||||
public static boolean hasSignedIn(Context context) {
|
||||
return EhApplication.getEhCookieStore(context).hasSignedIn() &&
|
||||
Settings.getDisplayName() != null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.client.parser;
|
||||
|
||||
import com.hippo.ehviewer.client.EhEngine;
|
||||
import com.hippo.ehviewer.client.EhException;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class SignInParser {
|
||||
|
||||
private static final Pattern NAME_PATTERN = Pattern.compile("<p>You are now logged in as: (.+?)<");
|
||||
private static final Pattern ERROR_PATTERN = Pattern.compile(
|
||||
"(?:<h4>The error returned was:</h4>\\s*<p>(.+?)</p>)"
|
||||
+ "|(?:<span class=\"postcolor\">(.+?)</span>)");
|
||||
|
||||
public static String parse(String body) throws Exception {
|
||||
Matcher m = NAME_PATTERN.matcher(body);
|
||||
if (m.find()) {
|
||||
return m.group(1);
|
||||
} else {
|
||||
m = ERROR_PATTERN.matcher(body);
|
||||
if (m.find()) {
|
||||
throw new EhException(m.group(1) == null ? m.group(2) : m.group(1));
|
||||
} else {
|
||||
throw new EhException(EhEngine.UNKNOWN);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.ui;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.design.widget.NavigationView;
|
||||
import android.support.v4.widget.DrawerLayout;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.Settings;
|
||||
import com.hippo.ehviewer.client.EhUtils;
|
||||
import com.hippo.ehviewer.ui.scene.GalleryListScene;
|
||||
import com.hippo.ehviewer.ui.scene.LoginScene;
|
||||
import com.hippo.ehviewer.ui.scene.WarningScene;
|
||||
import com.hippo.scene.StageActivity;
|
||||
|
||||
public final class MainActivity extends StageActivity
|
||||
implements NavigationView.OnNavigationItemSelectedListener {
|
||||
|
||||
private DrawerLayout mDrawerLayout;
|
||||
|
||||
@Override
|
||||
public int getContainerViewId() {
|
||||
return R.id.fragment_container;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
mDrawerLayout = (DrawerLayout) findViewById(R.id.draw_view);
|
||||
|
||||
NavigationView navView = (NavigationView) findViewById(R.id.nav_view);
|
||||
navView.setNavigationItemSelectedListener(this);
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
onInit();
|
||||
}
|
||||
}
|
||||
|
||||
public void setDrawerLayoutEnable(boolean enable) {
|
||||
if (enable) {
|
||||
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
|
||||
} else {
|
||||
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
|
||||
}
|
||||
}
|
||||
|
||||
private void onInit() {
|
||||
if (Settings.getShowWarning()) {
|
||||
setDrawerLayoutEnable(false);
|
||||
startScene(WarningScene.class);
|
||||
} else if (!EhUtils.hasSignedIn(this)) {
|
||||
setDrawerLayoutEnable(false);
|
||||
startScene(LoginScene.class);
|
||||
} else {
|
||||
setDrawerLayoutEnable(true);
|
||||
startScene(GalleryListScene.class);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onNavigationItemSelected(MenuItem item) {
|
||||
// Handle navigation view item clicks here.
|
||||
int id = item.getItemId();
|
||||
|
||||
if (id == R.id.nav_homepage) {
|
||||
|
||||
} else if (id == R.id.nav_whats_hot) {
|
||||
|
||||
} else if (id == R.id.nav_favourite) {
|
||||
|
||||
} else if (id == R.id.nav_history) {
|
||||
|
||||
} else if (id == R.id.nav_download) {
|
||||
|
||||
} else if (id == R.id.nav_settings) {
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.ui.scene;
|
||||
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
|
||||
import com.hippo.ehviewer.ui.MainActivity;
|
||||
import com.hippo.scene.SceneFragment;
|
||||
|
||||
public class BaseScene extends SceneFragment {
|
||||
|
||||
public void setDrawerLayoutEnable(boolean enable) {
|
||||
FragmentActivity activity = getActivity();
|
||||
if (activity instanceof MainActivity) {
|
||||
((MainActivity) activity).setDrawerLayoutEnable(enable);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.ui.scene;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.hippo.ehviewer.R;
|
||||
|
||||
public class GalleryListScene extends BaseScene {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
|
||||
View view = inflater.inflate(R.layout.scene_gallery_list, container, false);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return view;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.ui.scene;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.graphics.Paint;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.design.widget.TextInputLayout;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.hippo.ehviewer.EhApplication;
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.Settings;
|
||||
import com.hippo.ehviewer.client.EhClient;
|
||||
import com.hippo.ehviewer.client.EhCookieStore;
|
||||
import com.hippo.ehviewer.client.EhRequest;
|
||||
import com.hippo.utils.ExceptionUtils;
|
||||
|
||||
public final class LoginScene extends BaseScene implements EditText.OnEditorActionListener,
|
||||
View.OnClickListener {
|
||||
|
||||
private View mProgress;
|
||||
private TextInputLayout mUsernameLayout;
|
||||
private TextInputLayout mPasswordLayout;
|
||||
private EditText mUsername;
|
||||
private EditText mPassword;
|
||||
private View mRegister;
|
||||
private View mSignIn;
|
||||
private TextView mSignInViaWebview;
|
||||
private TextView mSignInViaCookies;
|
||||
|
||||
private EhClient mClient;
|
||||
private EhCookieStore mCookieStore;
|
||||
private EhRequest mSignInRequest;
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
mClient = EhApplication.getEhClient(getContext());
|
||||
mCookieStore = EhApplication.getEhCookieStore(getContext());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.scene_login, container, false);
|
||||
|
||||
View loginForm = view.findViewById(R.id.login_form);
|
||||
mProgress = view.findViewById(R.id.progress);
|
||||
mUsernameLayout = (TextInputLayout) loginForm.findViewById(R.id.username_layout);
|
||||
mUsername = mUsernameLayout.getEditText();
|
||||
mPasswordLayout = (TextInputLayout) loginForm.findViewById(R.id.password_layout);
|
||||
mPassword = mPasswordLayout.getEditText();
|
||||
mRegister = loginForm.findViewById(R.id.register);
|
||||
mSignIn = loginForm.findViewById(R.id.sign_in);
|
||||
mSignInViaWebview = (TextView) loginForm.findViewById(R.id.sign_in_via_webview);
|
||||
mSignInViaCookies = (TextView) loginForm.findViewById(R.id.sign_in_via_cookies);
|
||||
|
||||
mSignInViaWebview.setPaintFlags(mSignInViaWebview.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
|
||||
mSignInViaCookies.setPaintFlags(mSignInViaCookies.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
|
||||
|
||||
mPassword.setOnEditorActionListener(this);
|
||||
|
||||
mRegister.setOnClickListener(this);
|
||||
mSignIn.setOnClickListener(this);
|
||||
mSignInViaWebview.setOnClickListener(this);
|
||||
mSignInViaCookies.setOnClickListener(this);
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
|
||||
if (mSignInRequest != null) {
|
||||
mSignInRequest.cancel();
|
||||
mSignInRequest = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (mRegister == v) {
|
||||
|
||||
} else if (mSignIn == v) {
|
||||
signIn();
|
||||
} else if (mSignInViaWebview == v) {
|
||||
|
||||
} else if (mSignInViaCookies == v) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
|
||||
if (v == mPassword) {
|
||||
if (actionId == EditorInfo.IME_ACTION_DONE || actionId == EditorInfo.IME_NULL) {
|
||||
signIn();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void signIn() {
|
||||
if (mSignInRequest != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String username = mUsername.getText().toString();
|
||||
String password = mPassword.getText().toString();
|
||||
|
||||
if (username.isEmpty()) {
|
||||
mUsernameLayout.setError(getString(R.string.error_username_cannot_empty));
|
||||
return;
|
||||
} else {
|
||||
mUsernameLayout.setError(null);
|
||||
}
|
||||
|
||||
if (password.isEmpty()) {
|
||||
mPasswordLayout.setError(getString(R.string.error_password_cannot_empty));
|
||||
return;
|
||||
} else {
|
||||
mPasswordLayout.setError(null);
|
||||
}
|
||||
|
||||
// Hide ime keyboard
|
||||
View view = getActivity().getCurrentFocus();
|
||||
if (view != null) {
|
||||
InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
|
||||
}
|
||||
|
||||
mProgress.setAlpha(0.0f);
|
||||
mProgress.setVisibility(View.VISIBLE);
|
||||
mProgress.animate().alpha(1.0f).setDuration(500).start();
|
||||
|
||||
// Clean up for sign in
|
||||
mCookieStore.cleanUpForSignIn();
|
||||
|
||||
mSignInRequest = new EhRequest()
|
||||
.setMethod(EhClient.METHOD_SIGN_IN)
|
||||
.setArgs(username, password)
|
||||
.setCallback(new EhClient.Callback<String>() {
|
||||
@Override
|
||||
public void onSuccess(String result) {
|
||||
mSignInRequest = null;
|
||||
Settings.putDisplayName(result);
|
||||
|
||||
if (mCookieStore.hasSignedIn()) {
|
||||
// Has signed in
|
||||
redirectTo();
|
||||
} else {
|
||||
mProgress.setVisibility(View.GONE);
|
||||
whetherToSkip();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
mSignInRequest = null;
|
||||
mProgress.setVisibility(View.GONE);
|
||||
Toast.makeText(getContext(), ExceptionUtils.getReadableString(getContext(), e),
|
||||
Toast.LENGTH_SHORT).show();
|
||||
whetherToSkip();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel() {
|
||||
mSignInRequest = null;
|
||||
// User close this Scene
|
||||
}
|
||||
});
|
||||
mClient.execute(mSignInRequest);
|
||||
}
|
||||
|
||||
private void redirectTo() {
|
||||
startScene(GalleryListScene.class);
|
||||
finish();
|
||||
// Enable drawer
|
||||
setDrawerLayoutEnable(true);
|
||||
}
|
||||
|
||||
private void whetherToSkip() {
|
||||
new AlertDialog.Builder(getContext())
|
||||
.setTitle(R.string.skip_signing_in)
|
||||
.setMessage(R.string.skip_signing_in_plain)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
if (which == AlertDialog.BUTTON_POSITIVE) {
|
||||
redirectTo();
|
||||
}
|
||||
}
|
||||
}).show();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.ui.scene;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.Settings;
|
||||
import com.hippo.ehviewer.client.EhUtils;
|
||||
import com.hippo.vector.VectorDrawable;
|
||||
import com.hippo.widget.SimpleImageView;
|
||||
|
||||
public final class WarningScene extends BaseScene implements View.OnClickListener {
|
||||
|
||||
private View mCancel;
|
||||
private View mOk;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.scene_warning, container, false);
|
||||
|
||||
SimpleImageView alert = (SimpleImageView) view.findViewById(R.id.icon_alert);
|
||||
mCancel = view.findViewById(R.id.cancel);
|
||||
mOk = view.findViewById(R.id.ok);
|
||||
|
||||
Drawable drawable = VectorDrawable.create(getContext(), R.drawable.ic_alert);
|
||||
alert.setDrawable(drawable);
|
||||
|
||||
mCancel.setOnClickListener(this);
|
||||
mOk.setOnClickListener(this);
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (mCancel == v) {
|
||||
finishStage();
|
||||
} else if (mOk == v) {
|
||||
// Never show this warning anymore
|
||||
Settings.putShowWarning(false);
|
||||
|
||||
if (EhUtils.hasSignedIn(getContext())) {
|
||||
startScene(GalleryListScene.class);
|
||||
finish();
|
||||
// Enable drawer
|
||||
setDrawerLayoutEnable(true);
|
||||
} else {
|
||||
startScene(LoginScene.class);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.hippo.network;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import com.hippo.ehviewer.R;
|
||||
|
||||
public class StatusCodeException extends Exception {
|
||||
|
||||
private static final SparseArray<String> ERROR_MESSAGE_ARRAY = new SparseArray<>(24);
|
||||
private static final String DEFAULT_ERROR_MESSAGE = "Error response code";
|
||||
|
||||
private final int mResponseCode;
|
||||
private final String mMessage;
|
||||
|
||||
public static void initialize(Context context) {
|
||||
Resources resources = context.getApplicationContext().getResources();
|
||||
|
||||
ERROR_MESSAGE_ARRAY.append(400, resources.getString(R.string.error_status_code_400));
|
||||
ERROR_MESSAGE_ARRAY.append(401, resources.getString(R.string.error_status_code_401));
|
||||
ERROR_MESSAGE_ARRAY.append(402, resources.getString(R.string.error_status_code_402));
|
||||
ERROR_MESSAGE_ARRAY.append(403, resources.getString(R.string.error_status_code_403));
|
||||
ERROR_MESSAGE_ARRAY.append(404, resources.getString(R.string.error_status_code_404));
|
||||
ERROR_MESSAGE_ARRAY.append(405, resources.getString(R.string.error_status_code_405));
|
||||
ERROR_MESSAGE_ARRAY.append(406, resources.getString(R.string.error_status_code_406));
|
||||
ERROR_MESSAGE_ARRAY.append(407, resources.getString(R.string.error_status_code_407));
|
||||
ERROR_MESSAGE_ARRAY.append(408, resources.getString(R.string.error_status_code_408));
|
||||
ERROR_MESSAGE_ARRAY.append(409, resources.getString(R.string.error_status_code_409));
|
||||
ERROR_MESSAGE_ARRAY.append(410, resources.getString(R.string.error_status_code_410));
|
||||
ERROR_MESSAGE_ARRAY.append(411, resources.getString(R.string.error_status_code_411));
|
||||
ERROR_MESSAGE_ARRAY.append(412, resources.getString(R.string.error_status_code_412));
|
||||
ERROR_MESSAGE_ARRAY.append(413, resources.getString(R.string.error_status_code_413));
|
||||
ERROR_MESSAGE_ARRAY.append(414, resources.getString(R.string.error_status_code_414));
|
||||
ERROR_MESSAGE_ARRAY.append(415, resources.getString(R.string.error_status_code_415));
|
||||
ERROR_MESSAGE_ARRAY.append(416, resources.getString(R.string.error_status_code_416));
|
||||
ERROR_MESSAGE_ARRAY.append(417, resources.getString(R.string.error_status_code_417));
|
||||
|
||||
ERROR_MESSAGE_ARRAY.append(500, resources.getString(R.string.error_status_code_500));
|
||||
ERROR_MESSAGE_ARRAY.append(501, resources.getString(R.string.error_status_code_501));
|
||||
ERROR_MESSAGE_ARRAY.append(502, resources.getString(R.string.error_status_code_502));
|
||||
ERROR_MESSAGE_ARRAY.append(503, resources.getString(R.string.error_status_code_503));
|
||||
ERROR_MESSAGE_ARRAY.append(504, resources.getString(R.string.error_status_code_504));
|
||||
ERROR_MESSAGE_ARRAY.append(505, resources.getString(R.string.error_status_code_505));
|
||||
}
|
||||
|
||||
public StatusCodeException(int responseCode) {
|
||||
mResponseCode = responseCode;
|
||||
mMessage = ERROR_MESSAGE_ARRAY.get(responseCode, DEFAULT_ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
public StatusCodeException(int responseCode, String message) {
|
||||
mResponseCode = responseCode;
|
||||
mMessage = message;
|
||||
}
|
||||
|
||||
public int getResponseCode() {
|
||||
return mResponseCode;
|
||||
}
|
||||
|
||||
public boolean isIdentifiedResponseCode() {
|
||||
return !DEFAULT_ERROR_MESSAGE.equals(mMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return mMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLocalizedMessage() {
|
||||
return getMessage();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.hippo.okhttp;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
import okhttp3.Request;
|
||||
|
||||
public class ChromeRequestBuilder extends Request.Builder {
|
||||
|
||||
private static final String CHROME_USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " +
|
||||
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.111 Safari/537.36";
|
||||
|
||||
public ChromeRequestBuilder(String url) {
|
||||
URL u;
|
||||
try {
|
||||
u = new URL(url);
|
||||
} catch (MalformedURLException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
|
||||
url(u);
|
||||
|
||||
addHeader("User-Agent", CHROME_USER_AGENT);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.hippo.okhttp;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.hippo.okhttp.dao.DaoMaster;
|
||||
import com.hippo.okhttp.dao.DaoSession;
|
||||
import com.hippo.okhttp.dao.OkHttp3CookieDao;
|
||||
import com.hippo.okhttp.dao.OkHttp3CookieRaw;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import okhttp3.Cookie;
|
||||
|
||||
public class CookieDB {
|
||||
|
||||
private static DaoSession sDaoSession;
|
||||
|
||||
public static class DBOpenHelper extends DaoMaster.OpenHelper {
|
||||
|
||||
public DBOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory) {
|
||||
super(context, name, factory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
}
|
||||
}
|
||||
|
||||
public static void initialize(Context context) {
|
||||
DBOpenHelper helper = new DBOpenHelper(
|
||||
context.getApplicationContext(), "okhttp3-cookie.db", null);
|
||||
|
||||
SQLiteDatabase db = helper.getWritableDatabase();
|
||||
DaoMaster daoMaster = new DaoMaster(db);
|
||||
|
||||
sDaoSession = daoMaster.newSession();
|
||||
}
|
||||
|
||||
public static String cookiesDomain(URL url) {
|
||||
return cookiesDomain(url.getHost());
|
||||
}
|
||||
|
||||
public static String cookiesDomain(String domain) {
|
||||
if (TextUtils.isEmpty(domain)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
for (int i = domain.length() - 1; i >= 0; i--) {
|
||||
char ch = domain.charAt(i);
|
||||
if (ch == '.') {
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count == 2) {
|
||||
return domain.substring(i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
return domain;
|
||||
}
|
||||
|
||||
public static Map<String, List<CookieWithID>> getAllCookies() {
|
||||
OkHttp3CookieDao dao = sDaoSession.getOkHttp3CookieDao();
|
||||
List<OkHttp3CookieRaw> list = dao.queryBuilder().list();
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
Map<String, List<CookieWithID>> result = new HashMap<>();
|
||||
for (OkHttp3CookieRaw raw : list) {
|
||||
// Check expired
|
||||
if (!raw.getPersistent() || raw.getExpiresAt() <= now) {
|
||||
dao.delete(raw);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Avoid null error
|
||||
String name = raw.getName();
|
||||
String value = raw.getValue();
|
||||
String domain = raw.getDomain();
|
||||
if (name == null || value == null || domain == null) {
|
||||
dao.delete(raw);
|
||||
continue;
|
||||
}
|
||||
|
||||
Cookie.Builder builder = new Cookie.Builder();
|
||||
builder.name(name);
|
||||
builder.value(value);
|
||||
builder.expiresAt(raw.getExpiresAt());
|
||||
if (raw.getHostOnly()) {
|
||||
builder.hostOnlyDomain(domain);
|
||||
} else {
|
||||
builder.domain(raw.getDomain());
|
||||
}
|
||||
builder.path(raw.getPath());
|
||||
if (raw.getSecure()) {
|
||||
builder.secure();
|
||||
}
|
||||
if (raw.getHttpOnly()) {
|
||||
builder.httpOnly();
|
||||
}
|
||||
|
||||
String cookiesDomain = cookiesDomain(domain);
|
||||
|
||||
List<CookieWithID> cookies = result.get(cookiesDomain);
|
||||
if (cookies == null) {
|
||||
cookies = new ArrayList<>();
|
||||
result.put(cookiesDomain, cookies);
|
||||
}
|
||||
|
||||
cookies.add(new CookieWithID(raw.getId(), builder.build()));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void removeCookie(long id) {
|
||||
sDaoSession.getOkHttp3CookieDao().deleteByKey(id);
|
||||
}
|
||||
|
||||
public static long addCookie(Cookie cookie) {
|
||||
OkHttp3CookieDao dao = sDaoSession.getOkHttp3CookieDao();
|
||||
|
||||
OkHttp3CookieRaw raw = new OkHttp3CookieRaw();
|
||||
raw.setName(cookie.name());
|
||||
raw.setValue(cookie.value());
|
||||
raw.setExpiresAt(cookie.expiresAt());
|
||||
raw.setDomain(cookie.domain());
|
||||
raw.setPath(cookie.path());
|
||||
raw.setSecure(cookie.secure());
|
||||
raw.setHttpOnly(cookie.httpOnly());
|
||||
raw.setPersistent(cookie.persistent());
|
||||
raw.setHostOnly(cookie.hostOnly());
|
||||
|
||||
return dao.insert(raw);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.hippo.okhttp;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import okhttp3.Cookie;
|
||||
import okhttp3.CookieJar;
|
||||
import okhttp3.HttpUrl;
|
||||
import okhttp3.Request;
|
||||
|
||||
public class CookieDBStore implements CookieJar {
|
||||
|
||||
private final Map<String, List<CookieWithID>> map;
|
||||
|
||||
public CookieDBStore() {
|
||||
map = CookieDB.getAllCookies();
|
||||
}
|
||||
|
||||
private boolean hasExpired(Cookie cookie) {
|
||||
return cookie.expiresAt() < System.currentTimeMillis();
|
||||
}
|
||||
|
||||
private static CookieWithID removeCookie(List<CookieWithID> list, Cookie cookie) {
|
||||
for (int i = 0, n = list.size(); i < n; i++) {
|
||||
CookieWithID cwi = list.get(i);
|
||||
if (cwi.cookie.name().equals(cookie.name())) {
|
||||
list.remove(i);
|
||||
return cwi;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static CookieWithID removeCookie(List<CookieWithID> list, String name) {
|
||||
for (int i = 0, n = list.size(); i < n; i++) {
|
||||
CookieWithID cwi = list.get(i);
|
||||
if (cwi.cookie.name().equals(name)) {
|
||||
list.remove(i);
|
||||
return cwi;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean containInternal(String domain, String name) {
|
||||
List<CookieWithID> cookies = map.get(domain);
|
||||
if (cookies != null) {
|
||||
for (int i = 0, n = cookies.size(); i < n; i++) {
|
||||
CookieWithID cwi = cookies.get(i);
|
||||
if (cwi.cookie.name().equals(name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private synchronized void removeInternal(String domain, Cookie cookie) {
|
||||
List<CookieWithID> cookies = map.get(domain);
|
||||
if (cookies != null) {
|
||||
// Remove from list
|
||||
CookieWithID cwi = removeCookie(cookies, cookie);
|
||||
if (cwi != null) {
|
||||
// Remove from DB
|
||||
CookieDB.removeCookie(cwi.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void removeInternal(String domain, String name) {
|
||||
List<CookieWithID> cookies = map.get(domain);
|
||||
if (cookies != null) {
|
||||
// Remove from list
|
||||
CookieWithID cwi = removeCookie(cookies, name);
|
||||
if (cwi != null) {
|
||||
// Remove from DB
|
||||
CookieDB.removeCookie(cwi.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void addInternal(String domain, Cookie cookie) {
|
||||
// Check expired
|
||||
if (hasExpired(cookie)) {
|
||||
removeInternal(domain, cookie);
|
||||
return;
|
||||
}
|
||||
|
||||
List<CookieWithID> cookies = map.get(domain);
|
||||
if (cookies == null) {
|
||||
cookies = new ArrayList<>();
|
||||
map.put(domain, cookies);
|
||||
} else {
|
||||
// Remove from list
|
||||
CookieWithID cwi = removeCookie(cookies, cookie);
|
||||
if (cwi != null) {
|
||||
// Remove from DB
|
||||
CookieDB.removeCookie(cwi.id);
|
||||
}
|
||||
}
|
||||
|
||||
// Add to DB
|
||||
long id = CookieDB.addCookie(cookie);
|
||||
// Add to list
|
||||
cookies.add(new CookieWithID(id, cookie));
|
||||
}
|
||||
|
||||
public boolean contain(String url, String name) {
|
||||
return containInternal(CookieDB.cookiesDomain(url), name);
|
||||
}
|
||||
|
||||
public void remove(String url, String name) {
|
||||
removeInternal(CookieDB.cookiesDomain(url), name);
|
||||
}
|
||||
|
||||
public void add(Cookie cookie) {
|
||||
addInternal(CookieDB.cookiesDomain(cookie.domain()), cookie);
|
||||
}
|
||||
|
||||
public List<Cookie> get(HttpUrl url) {
|
||||
List<Cookie> result = new ArrayList<>();
|
||||
|
||||
String domain = CookieDB.cookiesDomain(url.url());
|
||||
List<CookieWithID> cookies = map.get(domain);
|
||||
if (cookies != null) {
|
||||
for (Iterator<CookieWithID> i = cookies.iterator(); i.hasNext();) {
|
||||
CookieWithID cwi = i.next();
|
||||
Cookie cookie = cwi.cookie;
|
||||
// Check expired
|
||||
if (hasExpired(cookie)) {
|
||||
// Remove from list
|
||||
i.remove();
|
||||
// Remove from DB
|
||||
CookieDB.removeCookie(cwi.id);
|
||||
} else if (cookie.matches(url)) {
|
||||
result.add(cookie);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Collections.unmodifiableList(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
|
||||
for (Cookie cookie: cookies) {
|
||||
add(cookie);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Cookie> loadForRequest(HttpUrl url, Request request) {
|
||||
return get(url);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.hippo.okhttp;
|
||||
|
||||
import okhttp3.Cookie;
|
||||
|
||||
public class CookieWithID {
|
||||
|
||||
public long id;
|
||||
public Cookie cookie;
|
||||
|
||||
public CookieWithID(long id, Cookie cookie) {
|
||||
this.id = id;
|
||||
this.cookie = cookie;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.hippo.scene;
|
||||
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
|
||||
public class SceneFragment extends Fragment {
|
||||
|
||||
public <T extends SceneFragment> void startScene(Class<T> clazz) {
|
||||
FragmentActivity activity = getActivity();
|
||||
if (activity instanceof StageActivity) {
|
||||
((StageActivity) activity).startScene(clazz);
|
||||
}
|
||||
}
|
||||
|
||||
public void finish() {
|
||||
FragmentActivity activity = getActivity();
|
||||
if (activity instanceof StageActivity) {
|
||||
((StageActivity) activity).finishScene(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void finishStage() {
|
||||
FragmentActivity activity = getActivity();
|
||||
if (activity != null) {
|
||||
activity.finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.hippo.scene;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.util.Log;
|
||||
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.yorozuya.IdIntGenerator;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
||||
public abstract class StageActivity extends AppCompatActivity {
|
||||
|
||||
private static final String TAG = StageActivity.class.getSimpleName();
|
||||
|
||||
private static final String KEY_STAGE_ACTIVITY_SCENE_TAG_LIST = "stage_activity_scene_tag_list";
|
||||
|
||||
// TODO ArrayList or LinkedList
|
||||
private ArrayList<String> mSceneTagList = new ArrayList<>();
|
||||
private IdIntGenerator mIdGenerator = new IdIntGenerator();
|
||||
|
||||
public abstract int getContainerViewId();
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
private <T extends SceneFragment> SceneFragment newSceneInstance(Class<T> clazz) {
|
||||
try {
|
||||
return clazz.newInstance();
|
||||
} catch (InstantiationException e) {
|
||||
throw new IllegalStateException("Can't instance " + clazz.getName(), e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new IllegalStateException("The constructor of " +
|
||||
clazz.getName() + " is not visible", e);
|
||||
} catch (ClassCastException e) {
|
||||
throw new IllegalStateException(clazz.getName() + " can not cast to scene", e);
|
||||
}
|
||||
}
|
||||
|
||||
public <T extends SceneFragment> void startScene(Class<T> clazz) {
|
||||
startScene(clazz, null);
|
||||
}
|
||||
|
||||
public <T extends SceneFragment> void startScene(Class<T> clazz, Bundle args) {
|
||||
FragmentManager fragmentManager = getSupportFragmentManager();
|
||||
|
||||
// Old scene
|
||||
Fragment old = null;
|
||||
if (mSceneTagList.size() > 0) {
|
||||
// Get last tag
|
||||
String tag = mSceneTagList.get(mSceneTagList.size() - 1);
|
||||
old = fragmentManager.findFragmentByTag(tag);
|
||||
}
|
||||
|
||||
// New scene
|
||||
SceneFragment scene = newSceneInstance(clazz);
|
||||
scene.setArguments(args);
|
||||
// New scene tag
|
||||
String newTag = Integer.toString(mIdGenerator.nextId());
|
||||
mSceneTagList.add(newTag);
|
||||
|
||||
FragmentTransaction transaction = fragmentManager.beginTransaction();
|
||||
transaction.setCustomAnimations(R.anim.fragment_translate_in, R.anim.fragment_translate_out);
|
||||
if (old != null) {
|
||||
transaction.detach(old);
|
||||
}
|
||||
transaction.add(getContainerViewId(), scene, newTag);
|
||||
transaction.commit();
|
||||
}
|
||||
|
||||
public void finishScene(SceneFragment scene) {
|
||||
finishScene(scene.getTag());
|
||||
}
|
||||
|
||||
|
||||
private void finishScene(String tag) {
|
||||
FragmentManager fragmentManager = getSupportFragmentManager();
|
||||
|
||||
// Get scene
|
||||
Fragment scene = fragmentManager.findFragmentByTag(tag);
|
||||
if (scene == null) {
|
||||
Log.e(TAG, "finishScene: Can't find scene by tag: " + tag);
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME It will fail if mIdGenerator.nextId() called more than Integer.MAX_VALUE times
|
||||
// Get scene index
|
||||
int index = Collections.binarySearch(mSceneTagList, tag);
|
||||
if (index < 0) {
|
||||
Log.e(TAG, "finishScene: Can't find the tag in tag list: " + tag);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mSceneTagList.size() == 1) {
|
||||
// It is the last fragment, finish Activity now
|
||||
Log.i(TAG, "finishScene: It is the last scene, finish activity now");
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
Fragment next = null;
|
||||
// It is first fragment, show the next one
|
||||
if (index == mSceneTagList.size() - 1) {
|
||||
next = fragmentManager.findFragmentByTag(mSceneTagList.get(index - 1));
|
||||
}
|
||||
|
||||
FragmentTransaction transaction = fragmentManager.beginTransaction();
|
||||
transaction.setCustomAnimations(R.anim.fragment_translate_in, R.anim.fragment_translate_out);
|
||||
transaction.remove(scene);
|
||||
if (next != null && next.isDetached()) {
|
||||
transaction.attach(next);
|
||||
}
|
||||
transaction.commit();
|
||||
|
||||
// Remove tag
|
||||
mSceneTagList.remove(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
int size = mSceneTagList.size();
|
||||
if (size > 0) {
|
||||
finishScene(mSceneTagList.get(size - 1));
|
||||
} else {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putStringArrayList(KEY_STAGE_ACTIVITY_SCENE_TAG_LIST, mSceneTagList);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(Bundle savedInstanceState) {
|
||||
super.onRestoreInstanceState(savedInstanceState);
|
||||
mSceneTagList = savedInstanceState.getStringArrayList(KEY_STAGE_ACTIVITY_SCENE_TAG_LIST);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.hippo.utils;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.client.EhException;
|
||||
import com.hippo.network.StatusCodeException;
|
||||
|
||||
import org.apache.http.conn.ConnectTimeoutException;
|
||||
|
||||
import java.net.ProtocolException;
|
||||
import java.net.SocketException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
public final class ExceptionUtils {
|
||||
|
||||
private static final String TAG = ExceptionUtils.class.getSimpleName();
|
||||
|
||||
@NonNull
|
||||
public static String getReadableString(@NonNull Context context, @NonNull Exception e) {
|
||||
if (e instanceof ConnectTimeoutException ||
|
||||
e instanceof SocketTimeoutException) {
|
||||
return context.getString(R.string.error_timeout);
|
||||
} else if (e instanceof UnknownHostException) {
|
||||
return context.getString(R.string.error_unknown_host);
|
||||
} else if (e instanceof StatusCodeException) {
|
||||
StatusCodeException sce = (StatusCodeException) e;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(context.getString(R.string.error_bad_status_code, sce.getResponseCode()));
|
||||
if (sce.isIdentifiedResponseCode()) {
|
||||
sb.append(", ").append(sce.getMessage());
|
||||
}
|
||||
return sb.toString();
|
||||
} else if (e instanceof ProtocolException && e.getMessage().startsWith("Too many follow-up requests:")) {
|
||||
return context.getString(R.string.error_redirection);
|
||||
} else if (e instanceof ProtocolException || e instanceof SocketException) {
|
||||
return context.getString(R.string.error_socket);
|
||||
} else if (e instanceof EhException) {
|
||||
return e.getMessage();
|
||||
} else {
|
||||
return context.getString(R.string.error_unknown);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.hippo.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.yorozuya.AssertUtils;
|
||||
|
||||
public class MaxSizeContainer extends ViewGroup {
|
||||
|
||||
private int mMaxWidth;
|
||||
private int mMaxHeight;
|
||||
|
||||
public MaxSizeContainer(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(context, attrs);
|
||||
}
|
||||
|
||||
public MaxSizeContainer(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init(context, attrs);
|
||||
}
|
||||
|
||||
private void init(Context context, AttributeSet attrs) {
|
||||
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MaxSizeContainer);
|
||||
mMaxWidth = a.getDimensionPixelOffset(R.styleable.MaxSizeContainer_maxWidth, -1);
|
||||
mMaxHeight = a.getDimensionPixelOffset(R.styleable.MaxSizeContainer_maxHeight, -1);
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
private int getMeasureSpec(int measureSpec, int max) {
|
||||
if (max < 0) {
|
||||
return measureSpec;
|
||||
}
|
||||
|
||||
int size = MeasureSpec.getSize(measureSpec);
|
||||
int mode = MeasureSpec.getMode(measureSpec);
|
||||
|
||||
switch (mode) {
|
||||
case MeasureSpec.AT_MOST:
|
||||
size = Math.min(size, max);
|
||||
break;
|
||||
case MeasureSpec.UNSPECIFIED:
|
||||
size = max;
|
||||
mode = MeasureSpec.AT_MOST;
|
||||
break;
|
||||
}
|
||||
return MeasureSpec.makeMeasureSpec(size, mode);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
AssertUtils.assertEquals("getChildCount() must be 1", 1, getChildCount());
|
||||
|
||||
View child = getChildAt(0);
|
||||
if (child.getVisibility() != GONE) {
|
||||
child.measure(getMeasureSpec(widthMeasureSpec, mMaxWidth),
|
||||
getMeasureSpec(heightMeasureSpec, mMaxHeight));
|
||||
setMeasuredDimension(child.getMeasuredWidth(), child.getMeasuredHeight());
|
||||
} else {
|
||||
setMeasuredDimension(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
||||
AssertUtils.assertEquals("getChildCount() must be 1", 1, getChildCount());
|
||||
|
||||
View child = getChildAt(0);
|
||||
if (child.getVisibility() != GONE) {
|
||||
child.layout(0, 0, r - l, b - t);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,317 @@
|
||||
/*
|
||||
* Copyright 2015 Hippo Seven
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.hippo.widget;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.RectF;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.view.ViewCompat;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.view.animation.LinearInterpolator;
|
||||
|
||||
import com.hippo.anani.PathInterpolator;
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.yorozuya.ViewUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
// Base on android.graphics.drawable.MaterialProgressDrawable in L preview
|
||||
public class ProgressView extends View {
|
||||
|
||||
private static final Interpolator TRIM_START_INTERPOLATOR;
|
||||
private static final Interpolator TRIM_END_INTERPOLATOR;
|
||||
private static final Interpolator LINEAR_INTERPOLATOR = new LinearInterpolator();
|
||||
|
||||
static {
|
||||
Path trimStartPath = new Path();
|
||||
trimStartPath.moveTo(0.0f, 0.0f);
|
||||
trimStartPath.lineTo(0.5f, 0.0f);
|
||||
trimStartPath.cubicTo(0.7f, 0.0f, 0.6f, 1f, 1f, 1f);
|
||||
TRIM_START_INTERPOLATOR = PathInterpolator.build(trimStartPath);
|
||||
|
||||
Path trimEndPath = new Path();
|
||||
trimEndPath.moveTo(0.0f, 0.0f);
|
||||
trimEndPath.cubicTo(0.2f, 0.0f, 0.1f, 1f, 0.5f, 1f);
|
||||
trimEndPath.lineTo(1f, 1f);
|
||||
TRIM_END_INTERPOLATOR = PathInterpolator.build(trimEndPath);
|
||||
}
|
||||
|
||||
private final ArrayList<Animator> mAnimators = new ArrayList<>();
|
||||
private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
private final RectF mRectF = new RectF();
|
||||
|
||||
private boolean mIndeterminate;
|
||||
|
||||
private float mTrimStart = 0.0f;
|
||||
private float mTrimEnd = 0.0f;
|
||||
private float mTrimOffset = 0.0f;
|
||||
private float mTrimRotation = 0.0f;
|
||||
|
||||
// It is a trick to avoid first sight stuck. Get it from ProgressBar
|
||||
private boolean mShouldStartAnimationDrawable = false;
|
||||
|
||||
public ProgressView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(context, attrs);
|
||||
}
|
||||
|
||||
public ProgressView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init(context, attrs);
|
||||
}
|
||||
|
||||
private void init(Context context, AttributeSet attrs) {
|
||||
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ProgressView);
|
||||
int color = a.getColor(R.styleable.ProgressView_color, Color.BLACK);
|
||||
mPaint.setColor(color);
|
||||
mPaint.setStrokeCap(Paint.Cap.SQUARE);
|
||||
mPaint.setStrokeJoin(Paint.Join.MITER);
|
||||
mPaint.setStyle(Paint.Style.STROKE);
|
||||
mIndeterminate = a.getBoolean(R.styleable.ProgressView_indeterminate, true);
|
||||
setProgress(a.getFloat(R.styleable.ProgressView_progress, 0f));
|
||||
a.recycle();
|
||||
|
||||
setupAnimators();
|
||||
}
|
||||
|
||||
private void setupAnimators() {
|
||||
ObjectAnimator trimStart = ObjectAnimator.ofFloat(this, "trimStart", 0.0f, 0.75f);
|
||||
trimStart.setDuration(1333L);
|
||||
trimStart.setInterpolator(TRIM_START_INTERPOLATOR);
|
||||
trimStart.setRepeatCount(Animation.INFINITE);
|
||||
|
||||
ObjectAnimator trimEnd = ObjectAnimator.ofFloat(this, "trimEnd", 0.0f, 0.75f);
|
||||
trimEnd.setDuration(1333L);
|
||||
trimEnd.setInterpolator(TRIM_END_INTERPOLATOR);
|
||||
trimEnd.setRepeatCount(Animation.INFINITE);
|
||||
|
||||
ObjectAnimator trimOffset = ObjectAnimator.ofFloat(this, "trimOffset", 0.0f, 0.25f);
|
||||
trimOffset.setDuration(1333L);
|
||||
trimOffset.setInterpolator(LINEAR_INTERPOLATOR);
|
||||
trimOffset.setRepeatCount(Animation.INFINITE);
|
||||
|
||||
ObjectAnimator trimRotation = ObjectAnimator.ofFloat(this, "trimRotation", 0.0f, 720.0f);
|
||||
trimRotation.setDuration(6665L);
|
||||
trimRotation.setInterpolator(LINEAR_INTERPOLATOR);
|
||||
trimRotation.setRepeatCount(Animation.INFINITE);
|
||||
|
||||
mAnimators.add(trimStart);
|
||||
mAnimators.add(trimEnd);
|
||||
mAnimators.add(trimOffset);
|
||||
mAnimators.add(trimRotation);
|
||||
}
|
||||
|
||||
private void startAnimation() {
|
||||
mShouldStartAnimationDrawable = true;
|
||||
postInvalidate();
|
||||
}
|
||||
|
||||
private void startAnimationActually() {
|
||||
ArrayList<Animator> animators = mAnimators;
|
||||
int N = animators.size();
|
||||
for (int i = 0; i < N; i++) {
|
||||
Animator animator = animators.get(i);
|
||||
if (!animator.isRunning()) {
|
||||
animator.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void stopAnimation() {
|
||||
mShouldStartAnimationDrawable = false;
|
||||
ArrayList<Animator> animators = mAnimators;
|
||||
int N = animators.size();
|
||||
for (int i = 0; i < N; i++) {
|
||||
animators.get(i).cancel();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isRunning() {
|
||||
ArrayList<Animator> animators = mAnimators;
|
||||
int N = animators.size();
|
||||
for (int i = 0; i < N; i++) {
|
||||
Animator animator = animators.get(i);
|
||||
if (animator.isRunning()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public float getTrimStart() {
|
||||
return mTrimStart;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void setTrimStart(float trimStart) {
|
||||
mTrimStart = trimStart;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public float getTrimEnd() {
|
||||
return mTrimEnd;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void setTrimEnd(float trimEnd) {
|
||||
mTrimEnd = trimEnd;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public float getTrimOffset() {
|
||||
return mTrimOffset;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void setTrimOffset(float trimOffset) {
|
||||
mTrimOffset = trimOffset;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public float getTrimRotation() {
|
||||
return mTrimRotation;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void setTrimRotation(float trimRotation) {
|
||||
mTrimRotation = trimRotation;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
if (mIndeterminate && getVisibility() == VISIBLE) {
|
||||
startAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetachedFromWindow() {
|
||||
if (mIndeterminate) {
|
||||
stopAnimation();
|
||||
}
|
||||
// This should come after stopAnimation(), otherwise an invalidate message remains in the
|
||||
// queue, which can prevent the entire view hierarchy from being GC'ed during a rotation
|
||||
super.onDetachedFromWindow();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setVisibility(int v) {
|
||||
if (getVisibility() != v) {
|
||||
super.setVisibility(v);
|
||||
|
||||
if (mIndeterminate) {
|
||||
if (v == GONE || v == INVISIBLE) {
|
||||
stopAnimation();
|
||||
} else if (ViewCompat.isAttachedToWindow(this)) {
|
||||
startAnimation();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onVisibilityChanged(@NonNull View changedView, int visibility) {
|
||||
super.onVisibilityChanged(changedView, visibility);
|
||||
|
||||
if (mIndeterminate && ViewCompat.isAttachedToWindow(this)) {
|
||||
if (visibility == GONE || visibility == INVISIBLE) {
|
||||
stopAnimation();
|
||||
} else if (ViewCompat.isAttachedToWindow(this)) {
|
||||
startAnimation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setColor(int color) {
|
||||
mPaint.setColor(color);
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void setIndeterminate(boolean indeterminate) {
|
||||
if (mIndeterminate != indeterminate) {
|
||||
mIndeterminate = indeterminate;
|
||||
if (indeterminate) {
|
||||
if (isShown() && ViewCompat.isAttachedToWindow(this)) {
|
||||
startAnimation();
|
||||
}
|
||||
} else {
|
||||
stopAnimation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isIndeterminate() {
|
||||
return mIndeterminate;
|
||||
}
|
||||
|
||||
public void setProgress(float progress) {
|
||||
if (!mIndeterminate) {
|
||||
mTrimStart = 0f;
|
||||
mTrimEnd = progress;
|
||||
mTrimOffset = 0f;
|
||||
mTrimRotation = 0f;
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
setMeasuredDimension(ViewUtils.getSuitableSize(getSuggestedMinimumWidth(), widthMeasureSpec),
|
||||
ViewUtils.getSuitableSize(getSuggestedMinimumHeight(), heightMeasureSpec));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||
mPaint.setStrokeWidth(Math.min(w, h) / 12.0f);
|
||||
mRectF.set(0, 0, w, h);
|
||||
mRectF.inset(w / 48.0f * 5.0f, h / 48.0f * 5.0f);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
int saved = canvas.save();
|
||||
canvas.rotate(mTrimRotation, mRectF.centerX(), mRectF.centerY());
|
||||
|
||||
float startAngle = (mTrimStart + mTrimOffset) * 360.0f - 90;
|
||||
float sweepAngle = (mTrimEnd - mTrimStart) * 360.0f;
|
||||
canvas.drawArc(mRectF, startAngle, sweepAngle, false, mPaint);
|
||||
|
||||
canvas.restoreToCount(saved);
|
||||
|
||||
if (mShouldStartAnimationDrawable) {
|
||||
mShouldStartAnimationDrawable = false;
|
||||
startAnimationActually();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Hippo Seven
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.hippo.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.support.annotation.DrawableRes;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
import com.hippo.yorozuya.ViewUtils;
|
||||
|
||||
public class SimpleImageView extends View implements Drawable.Callback {
|
||||
|
||||
private Drawable mDrawable;
|
||||
|
||||
private static final int[] LAYOUT_ATTRS = new int[] {
|
||||
android.R.attr.src
|
||||
};
|
||||
|
||||
public SimpleImageView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(context, attrs);
|
||||
}
|
||||
|
||||
public SimpleImageView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init(context, attrs);
|
||||
}
|
||||
|
||||
private void init(Context context, AttributeSet attrs) {
|
||||
final TypedArray a = context.obtainStyledAttributes(attrs, LAYOUT_ATTRS);
|
||||
setDrawable(a.getDrawable(0));
|
||||
a.recycle();
|
||||
|
||||
// Mostly drawable is VectorDrawable, it has cache already
|
||||
setWillNotCacheDrawing(true);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public void setDrawable(@DrawableRes int resId) {
|
||||
setDrawable(getContext().getResources().getDrawable(resId));
|
||||
}
|
||||
|
||||
public void setDrawable(Drawable drawable) {
|
||||
if (mDrawable != null) {
|
||||
mDrawable.setCallback(null);
|
||||
}
|
||||
mDrawable = drawable;
|
||||
if (drawable != null) {
|
||||
drawable.setCallback(this);
|
||||
if (drawable.isStateful()) {
|
||||
drawable.setState(getDrawableState());
|
||||
}
|
||||
}
|
||||
requestLayout();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawableStateChanged() {
|
||||
super.drawableStateChanged();
|
||||
Drawable d = mDrawable;
|
||||
if (d != null && d.isStateful()) {
|
||||
d.setState(getDrawableState());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateDrawable(@NonNull Drawable who) {
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getSuggestedMinimumWidth() {
|
||||
int superMinWidth = super.getSuggestedMinimumWidth();
|
||||
return (mDrawable == null) ? superMinWidth :
|
||||
Math.max(superMinWidth, mDrawable.getMinimumWidth() + getPaddingLeft() + getPaddingRight());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getSuggestedMinimumHeight() {
|
||||
int superMinHeight = super.getSuggestedMinimumHeight();
|
||||
return (mDrawable == null) ? superMinHeight :
|
||||
Math.max(superMinHeight, mDrawable.getMinimumHeight() + getPaddingTop() + getPaddingBottom());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
setMeasuredDimension(ViewUtils.getSuitableSize(getSuggestedMinimumWidth(), widthMeasureSpec),
|
||||
ViewUtils.getSuitableSize(getSuggestedMinimumHeight(), heightMeasureSpec));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
super.onLayout(changed, left, top, right, bottom);
|
||||
int width = right - left;
|
||||
int height = bottom - top;
|
||||
if (mDrawable != null) {
|
||||
mDrawable.setBounds(getPaddingLeft(), getPaddingTop(),
|
||||
width - getPaddingRight(), height - getPaddingBottom());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
if (mDrawable != null) {
|
||||
mDrawable.draw(canvas);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user