diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 27eb8daf7..75b9a314f 100755
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -132,6 +132,12 @@
android:theme="@style/AppTheme.NoActionBar"
android:label="@string/set_pattern_protection"/>
+
+
diff --git a/app/src/main/java/com/hippo/ehviewer/client/EhUrl.java b/app/src/main/java/com/hippo/ehviewer/client/EhUrl.java
index d7e1bf2b8..1ee8516aa 100644
--- a/app/src/main/java/com/hippo/ehviewer/client/EhUrl.java
+++ b/app/src/main/java/com/hippo/ehviewer/client/EhUrl.java
@@ -52,6 +52,9 @@ public class EhUrl {
public static final String URL_FAVORITES_EX = HOST_EX + "favorites.php";
public static final String URL_FORUMS = "https://forums.e-hentai.org/";
+ public static final String UCONFIG_E = HOST_E + "uconfig.php";
+ public static final String UCONFIG_EX = HOST_EX + "uconfig.php";
+
private static final String URL_PREFIX_THUMB_E = "https://ehgt.org/t/";
private static final String URL_PREFIX_THUMB_EX = "https://exhentai.org/t/";
@@ -89,6 +92,16 @@ public class EhUrl {
}
}
+ public static String getUConfigUrl() {
+ switch (Settings.getGallerySite()) {
+ default:
+ case SITE_E:
+ return UCONFIG_E;
+ case SITE_EX:
+ return UCONFIG_EX;
+ }
+ }
+
public static String getGalleryDetailUrl(long gid, String token, int index, boolean allComment) {
UrlBuilder builder = new UrlBuilder(getHost() + "g/" + gid + '/' + token + '/');
if (index != 0) {
diff --git a/app/src/main/java/com/hippo/ehviewer/ui/UConfigActivity.java b/app/src/main/java/com/hippo/ehviewer/ui/UConfigActivity.java
new file mode 100644
index 000000000..3a68f2f8d
--- /dev/null
+++ b/app/src/main/java/com/hippo/ehviewer/ui/UConfigActivity.java
@@ -0,0 +1,255 @@
+/*
+ * Copyright 2018 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;
+
+/*
+ * Created by Hippo on 2018/2/9.
+ */
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.graphics.Bitmap;
+import android.os.Build;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v7.app.AlertDialog;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.webkit.CookieManager;
+import android.webkit.CookieSyncManager;
+import android.webkit.JsPromptResult;
+import android.webkit.JsResult;
+import android.webkit.WebChromeClient;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+import android.widget.EditText;
+import android.widget.TextView;
+import com.hippo.ehviewer.EhApplication;
+import com.hippo.ehviewer.R;
+import com.hippo.ehviewer.client.EhCookieStore;
+import com.hippo.ehviewer.client.EhUrl;
+import com.hippo.widget.ProgressView;
+import okhttp3.Cookie;
+import okhttp3.HttpUrl;
+
+public class UConfigActivity extends ToolbarActivity {
+
+ private WebView webView;
+ private ProgressView progress;
+ private String url;
+ private boolean loaded;
+
+ @SuppressLint("SetJavaScriptEnabled")
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // http://stackoverflow.com/questions/32284642/how-to-handle-an-uncatched-exception
+ CookieManager cookieManager = CookieManager.getInstance();
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ cookieManager.flush();
+ cookieManager.removeAllCookies(null);
+ cookieManager.removeSessionCookies(null);
+ } else {
+ CookieSyncManager cookieSyncManager = CookieSyncManager.createInstance(this);
+ cookieSyncManager.startSync();
+ cookieManager.removeAllCookie();
+ cookieManager.removeSessionCookie();
+ cookieSyncManager.stopSync();
+ }
+
+ // Copy cookies from okhttp cookie store to CookieManager
+ url = EhUrl.getUConfigUrl();
+ EhCookieStore store = EhApplication.getEhCookieStore(this);
+ for (Cookie cookie : store.getCookies(HttpUrl.parse(url))) {
+ cookieManager.setCookie(url, cookie.toString());
+ }
+
+ setContentView(R.layout.activity_u_config);
+ webView = (WebView) findViewById(R.id.webview);
+ webView.getSettings().setJavaScriptEnabled(true);
+ webView.setWebViewClient(new UConfigWebViewClient());
+ webView.setWebChromeClient(new UConfigWebChromeClient());
+ webView.loadUrl(url);
+ progress = (ProgressView) findViewById(R.id.progress);
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ super.onCreateOptionsMenu(menu);
+ getMenuInflater().inflate(R.menu.activity_u_config, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ finish();
+ return true;
+ case R.id.action_apply:
+ if (loaded) {
+ webView.loadUrl("javascript:"
+ + "(function() {\n"
+ + " var apply = document.getElementById(\"apply\").children[0];\n"
+ + " apply.click();\n"
+ + "})();");
+ }
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ private Cookie longLive(Cookie cookie) {
+ return new Cookie.Builder()
+ .name(cookie.name())
+ .value(cookie.value())
+ .domain(cookie.domain())
+ .path(cookie.path())
+ .expiresAt(Long.MAX_VALUE)
+ .build();
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ webView.destroy();
+
+ // Put cookies back to okhttp cookie store
+ CookieManager cookieManager = CookieManager.getInstance();
+ String cookiesString = cookieManager.getCookie(url);
+
+ if (cookiesString != null && !cookiesString.isEmpty()) {
+ EhCookieStore store = EhApplication.getEhCookieStore(this);
+ HttpUrl eUrl = HttpUrl.parse(EhUrl.HOST_E);
+ HttpUrl exUrl = HttpUrl.parse(EhUrl.HOST_EX);
+
+ // The cookies saved in the uconfig page should be shared between e and ex
+ for (String header : cookiesString.split(";")) {
+ Cookie eCookie = Cookie.parse(eUrl, header);
+ if (eCookie != null) {
+ store.addCookie(longLive(eCookie));
+ }
+
+ Cookie exCookie = Cookie.parse(exUrl, header);
+ if (exCookie != null) {
+ store.addCookie(longLive(exCookie));
+ }
+ }
+ }
+ }
+
+ private class UConfigWebViewClient extends WebViewClient {
+ @Override
+ public boolean shouldOverrideUrlLoading(WebView view, String url) {
+ // Never load other urls
+ return true;
+ }
+
+ @Override
+ public void onPageStarted(WebView view, String url, Bitmap favicon) {
+ progress.setVisibility(View.VISIBLE);
+ loaded = false;
+ }
+
+ @Override
+ public void onPageFinished(WebView view, String url) {
+ progress.setVisibility(View.GONE);
+ loaded = true;
+ }
+ }
+
+ private class UConfigWebChromeClient extends WebChromeClient {
+
+ private Context context = UConfigActivity.this;
+
+ @Override
+ public boolean onJsPrompt(WebView view, String url, String message, String defaultValue,
+ final JsPromptResult result) {
+
+ View promptView = UConfigActivity.this.getLayoutInflater()
+ .inflate(R.layout.dialog_js_prompt, null, false);
+ TextView messageView = (TextView) promptView.findViewById(R.id.message);
+ messageView.setText(message);
+ final EditText valueView = (EditText) promptView.findViewById(R.id.value);
+ valueView.setText(defaultValue);
+
+ new AlertDialog.Builder(context)
+ .setView(promptView)
+ .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ result.confirm(valueView.getText().toString());
+ }
+ })
+ .setOnCancelListener(new DialogInterface.OnCancelListener() {
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ result.cancel();
+ }
+ })
+ .show();
+
+ return true;
+ }
+
+ @Override
+ public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
+ new AlertDialog.Builder(context)
+ .setMessage(message)
+ .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ result.confirm();
+ }
+ })
+ .setOnCancelListener(new DialogInterface.OnCancelListener() {
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ result.cancel();
+ }
+ })
+ .show();
+
+ return true;
+ }
+
+ @Override
+ public boolean onJsConfirm(WebView view, String url, String message, final JsResult result) {
+ new AlertDialog.Builder(context)
+ .setMessage(message)
+ .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ result.confirm();
+ }
+ })
+ .setOnCancelListener(new DialogInterface.OnCancelListener() {
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ result.cancel();
+ }
+ })
+ .show();
+
+ return true;
+ }
+ }
+}
diff --git a/app/src/main/res/drawable/v_check_dark_x24.xml b/app/src/main/res/drawable/v_check_dark_x24.xml
new file mode 100644
index 000000000..695620ecf
--- /dev/null
+++ b/app/src/main/res/drawable/v_check_dark_x24.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_u_config.xml b/app/src/main/res/layout/activity_u_config.xml
new file mode 100644
index 000000000..841181f7f
--- /dev/null
+++ b/app/src/main/res/layout/activity_u_config.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/dialog_js_prompt.xml b/app/src/main/res/layout/dialog_js_prompt.xml
new file mode 100644
index 000000000..691f8b9f8
--- /dev/null
+++ b/app/src/main/res/layout/dialog_js_prompt.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/menu/activity_u_config.xml b/app/src/main/res/menu/activity_u_config.xml
new file mode 100644
index 000000000..a24c1244a
--- /dev/null
+++ b/app/src/main/res/menu/activity_u_config.xml
@@ -0,0 +1,28 @@
+
+
+
+
diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml
index f52b945e9..4dededdb7 100755
--- a/app/src/main/res/values-zh-rCN/strings.xml
+++ b/app/src/main/res/values-zh-rCN/strings.xml
@@ -348,6 +348,10 @@
设置
允许使用指纹解锁
+
+ EHentai 设置
+ 应用
+
第 %d 页
@string/refresh
@@ -365,6 +369,8 @@
天哪,我的老伙计,你要退出登录吗?我是说,你真的要退出登录吗?
是的,我是说,真的
已退出登录,重启应用以便再次登录
+ EHentai 设置
+ EHentai 网站上的设置
画廊站点
列表模式
详情
diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml
index e510553ae..fadf73abd 100755
--- a/app/src/main/res/values-zh-rHK/strings.xml
+++ b/app/src/main/res/values-zh-rHK/strings.xml
@@ -348,6 +348,10 @@
設置
允許使用指紋解鎖
+
+ EHentai 設置
+ 應用
+
第 %d 頁
@string/refresh
@@ -365,6 +369,8 @@
天哪,我的老夥計,你要退出登錄嗎?我是説,你真的要退出登錄嗎?
是的,我是説,真的
已退出登錄,重啟應用以便再次登錄
+ EHentai 設置
+ EHentai 網站上的設置
畫廊站點
列表模式
詳情
diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml
index 13e2bf6ec..4e2c00bae 100755
--- a/app/src/main/res/values-zh-rTW/strings.xml
+++ b/app/src/main/res/values-zh-rTW/strings.xml
@@ -348,6 +348,10 @@
設定
允許使用指紋解鎖
+
+ EHentai 設定
+ 應用
+
第 %d 頁
@string/refresh
@@ -365,6 +369,8 @@
天哪,老兄,你真的要登出嗎?我是說,你真的要登出嗎?
沒錯,我是說,對
已登出,重新啟動程式以再次登入
+ EHentai 設定
+ EHentai 網站上的設定
圖庫站台
列表模式
詳細資料
diff --git a/app/src/main/res/values/pathdata.xml b/app/src/main/res/values/pathdata.xml
index a13598bb4..c85e6adb1 100644
--- a/app/src/main/res/values/pathdata.xml
+++ b/app/src/main/res/values/pathdata.xml
@@ -60,6 +60,7 @@
M2,20L17,10L22,22M14,9L2,8L11,2Z
M17.65,6.35C16.2,4.9 14.21,4 12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20C15.73,20 18.84,17.45 19.73,14H17.65C16.83,16.33 14.61,18 12,18A6,6 0 0,1 6,12A6,6 0 0,1 12,6C13.66,6 15.14,6.69 16.22,7.78L13,11H20V4L17.65,6.35Z
M9,13A3,3 0 0,0 12,16A3,3 0 0,0 15,13A3,3 0 0,0 12,10A3,3 0 0,0 9,13M20,19.59V8L14,2H6A2,2 0 0,0 4,4V20A2,2 0 0,0 6,22H18C18.45,22 18.85,21.85 19.19,21.6L14.76,17.17C13.96,17.69 13,18 12,18A5,5 0 0,1 7,13A5,5 0 0,1 12,8A5,5 0 0,1 17,13C17,14 16.69,14.96 16.17,15.75L20,19.59Z
+ M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z
M12.88,2H4V11L14.97,22.14L24,13.1L12.88,2ZM7.26,5.26C7.96,4.58,9.06,4.58,9.74,5.26C10.42,5.96,10.42,7.06,9.74,7.74S7.94,8.42,7.26,7.74S6.58,5.94,7.26,5.26ZM14.98,19.3L8.76,12.95L14.88,6.83L21.18,13.11L14.98,19.31ZM11.6,21.56L10.23,23L0,12.74V5H2V11.9L11.6,21.56Z
M20.46,14.65C21.86,16.15,20.31,18.6,18.32,17.87C19.78,17.57,20.79,16.37,20.46,14.65ZM4.32,17.87C6.32,18.6,7.86,16.17,6.46,14.65C6.79,16.38,5.78,17.55,4.32,17.87ZM16.87,4.3C16.6,3.56,15.87,3,15,3C13.7,3,12.7,4.24,13.1,5.58C14.2,5.18,15.44,4.48,16.87,4.31ZM24,16C24,18.76,21.76,21,19,21C14.96,21,14.84,16.88,12,16.88S9.04,21,5,21C2.24,21,0,18.76,0,16C0,13.87,1.53,11.43,3.94,7.18C5.84,3.81,8.69,5.92,10.76,6.58C11.54,6.85,12.41,6.88,13.24,6.58C15.3,5.92,18.14,3.81,20.06,7.18C22.46,11.43,24,13.88,24,16ZM8,16C8,14.35,6.65,13,5,13S2,14.35,2,16S3.35,19,5,19S8,17.65,8,16ZM13,14C13,13.45,12.55,13,12,13S11,13.45,11,14S11.45,15,12,15S13,14.55,13,14ZM22,16C22,14.35,20.65,13,19,13S16,14.35,16,16S17.35,19,19,19S22,17.65,22,16ZM9,3C8.14,3,7.4,3.55,7.13,4.3C8.56,4.48,9.79,5.2,10.9,5.58C11.3,4.24,10.3,3,9,3Z
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 8498acbe8..9a9e1bd5c 100755
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -392,6 +392,10 @@
Set
Also allow unlock with fingerprint
+
+ EHentai settings
+ Apply
+
Page %d
@string/refresh
@@ -408,6 +412,8 @@
Do you really want to sign out?
@android:string/ok
Signed out, restart the application to sign in
+ EHentai settings
+ Settings on EHentai website
Gallery site
List mode
Detail
diff --git a/app/src/main/res/xml/eh_settings.xml b/app/src/main/res/xml/eh_settings.xml
index 7c79a0969..8c1d24a8a 100644
--- a/app/src/main/res/xml/eh_settings.xml
+++ b/app/src/main/res/xml/eh_settings.xml
@@ -32,6 +32,12 @@
app:entryValues="@array/gallery_site_entry_values"
android:defaultValue="1"/>
+
+
-
-
-
-
-
-
-
-