diff --git a/app/src/main/java/com/hippo/ehviewer/EhApplication.java b/app/src/main/java/com/hippo/ehviewer/EhApplication.java index 554082212..89308aea4 100644 --- a/app/src/main/java/com/hippo/ehviewer/EhApplication.java +++ b/app/src/main/java/com/hippo/ehviewer/EhApplication.java @@ -84,6 +84,7 @@ public class EhApplication extends RecordingApplication { private final HashMap mGlobalStuffMap = new HashMap<>(); private EhCookieStore mEhCookieStore; private EhClient mEhClient; + private EhProxySelector mEhProxySelector; private OkHttpClient mOkHttpClient; private ImageBitmapHelper mImageBitmapHelper; private Conaco mConaco; @@ -266,6 +267,15 @@ public class EhApplication extends RecordingApplication { return application.mEhClient; } + @NonNull + public static EhProxySelector getEhProxySelector(@NonNull Context context) { + EhApplication application = ((EhApplication) context.getApplicationContext()); + if (application.mEhProxySelector == null) { + application.mEhProxySelector = new EhProxySelector(); + } + return application.mEhProxySelector; + } + @NonNull public static OkHttpClient getOkHttpClient(@NonNull Context context) { EhApplication application = ((EhApplication) context.getApplicationContext()); @@ -276,6 +286,7 @@ public class EhApplication extends RecordingApplication { .writeTimeout(10, TimeUnit.SECONDS) .cookieJar(getEhCookieStore(application)) .dns(new EhDns(application)) + .proxySelector(getEhProxySelector(application)) .build(); } return application.mOkHttpClient; diff --git a/app/src/main/java/com/hippo/ehviewer/EhProxySelector.java b/app/src/main/java/com/hippo/ehviewer/EhProxySelector.java new file mode 100644 index 000000000..5a1177812 --- /dev/null +++ b/app/src/main/java/com/hippo/ehviewer/EhProxySelector.java @@ -0,0 +1,106 @@ +/* + * Copyright 2019 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.text.TextUtils; +import com.hippo.network.InetValidator; +import com.hippo.util.ExceptionUtils; +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.net.ProxySelector; +import java.net.SocketAddress; +import java.net.URI; +import java.util.Collections; +import java.util.List; + +public class EhProxySelector extends ProxySelector { + + public static final int TYPE_DIRECT = 0; + public static final int TYPE_SYSTEM = 1; + public static final int TYPE_HTTP = 2; + public static final int TYPE_SOCKS = 3; + + private ProxySelector delegation; + private ProxySelector alternative; + + EhProxySelector() { + alternative = ProxySelector.getDefault(); + if (alternative == null) { + alternative = new NullProxySelector(); + } + + updateProxy(); + } + + public void updateProxy() { + switch (Settings.getProxyType()) { + case TYPE_DIRECT: + delegation = new NullProxySelector(); + break; + default: + case TYPE_SYSTEM: + delegation = alternative; + break; + case TYPE_HTTP: + case TYPE_SOCKS: + delegation = null; + break; + } + } + + @Override + public List select(URI uri) { + int type = Settings.getProxyType(); + if (type == TYPE_HTTP || type == TYPE_SOCKS) { + try { + String ip = Settings.getProxyIp(); + int port = Settings.getProxyPort(); + if (!TextUtils.isEmpty(ip) && InetValidator.isValidInetPort(port)) { + InetAddress inetAddress = InetAddress.getByName(ip); + SocketAddress socketAddress = new InetSocketAddress(inetAddress, port); + return Collections.singletonList(new Proxy(type == TYPE_HTTP ? Proxy.Type.HTTP : Proxy.Type.SOCKS, socketAddress)); + } + } catch (Throwable t) { + ExceptionUtils.throwIfFatal(t); + } + } + + if (delegation != null) { + return delegation.select(uri); + } + + return alternative.select(uri); + } + + @Override + public void connectFailed(URI uri, SocketAddress sa, IOException ioe) { + if (delegation != null) { + delegation.select(uri); + } + } + + private static class NullProxySelector extends ProxySelector { + @Override + public List select(URI uri) { + return Collections.singletonList(Proxy.NO_PROXY); + } + @Override + public void connectFailed(URI uri, SocketAddress sa, IOException ioe) { } + } +} diff --git a/app/src/main/java/com/hippo/ehviewer/Settings.java b/app/src/main/java/com/hippo/ehviewer/Settings.java index e582a3d2f..b4fce1355 100755 --- a/app/src/main/java/com/hippo/ehviewer/Settings.java +++ b/app/src/main/java/com/hippo/ehviewer/Settings.java @@ -386,72 +386,6 @@ public class Settings { putString(KEY_EXCLUDED_LANGUAGES, value); } - private static final String KEY_HATH_PROXY = "hath_proxy"; - private static final boolean DEFAULT_HATH_PROXY = false; - - public static boolean getHathProxy() { - return getBoolean(KEY_HATH_PROXY, DEFAULT_HATH_PROXY); - } - - public static void putHathProxy(boolean value) { - if (value) { - sEhConfig.hahClientIp = Settings.getHathIp(); - sEhConfig.hahClientPort = Settings.getHathPort(); - sEhConfig.hahClientPasskey = Settings.getHathPasskey(); - } else { - sEhConfig.hahClientIp = DEFAULT_HATH_IP; - sEhConfig.hahClientPort = DEFAULT_HATH_PORT; - sEhConfig.hahClientPasskey = DEFAULT_HATH_PASSKEY; - } - sEhConfig.setDirty(); - putBoolean(KEY_HATH_PROXY, value); - } - - private static final String KEY_HATH_IP = "hath_ip"; - private static final String DEFAULT_HATH_IP = null; - - public static String getHathIp() { - return getString(KEY_HATH_IP, DEFAULT_HATH_IP); - } - - public static void putHathIp(String value) { - if (Settings.getHathProxy()) { - sEhConfig.hahClientIp = value; - sEhConfig.setDirty(); - } - putString(KEY_HATH_IP, value); - } - - private static final String KEY_HATH_PORT = "hath_port"; - private static final int DEFAULT_HATH_PORT = -1; - - public static int getHathPort() { - return getInt(KEY_HATH_PORT, DEFAULT_HATH_PORT); - } - - public static void putHathPort(int value) { - if (Settings.getHathProxy()) { - sEhConfig.hahClientPort = value; - sEhConfig.setDirty(); - } - putInt(KEY_HATH_PORT, value); - } - - private static final String KEY_HATH_PASSKEY = "hath_passkey"; - private static final String DEFAULT_HATH_PASSKEY = null; - - public static String getHathPasskey() { - return getString(KEY_HATH_PASSKEY, DEFAULT_HATH_PASSKEY); - } - - public static void putHathPasskey(String value) { - if (Settings.getHathProxy()) { - sEhConfig.hahClientPasskey = value; - sEhConfig.setDirty(); - } - putString(KEY_HATH_PASSKEY, value); - } - private static final String KEY_CELLULAR_NETWORK_WARNING = "cellular_network_warning"; private static final boolean DEFAULT_CELLULAR_NETWORK_WARNING = false; @@ -1066,6 +1000,39 @@ public class Settings { putString(KEY_APP_LANGUAGE, value); } + private static final String KEY_PROXY_TYPE = "proxy_type"; + private static final int DEFAULT_PROXY_TYPE = EhProxySelector.TYPE_SYSTEM; + + public static int getProxyType() { + return getInt(KEY_PROXY_TYPE, DEFAULT_PROXY_TYPE); + } + + public static void putProxyType(int value) { + putInt(KEY_PROXY_TYPE, value); + } + + private static final String KEY_PROXY_IP = "proxy_ip"; + private static final String DEFAULT_PROXY_IP = null; + + public static String getProxyIp() { + return getString(KEY_PROXY_IP, DEFAULT_PROXY_IP); + } + + public static void putProxyIp(String value) { + putString(KEY_PROXY_IP, value); + } + + private static final String KEY_PROXY_PORT = "proxy_port"; + private static final int DEFAULT_PROXY_PORT = -1; + + public static int getProxyPort() { + return getInt(KEY_PROXY_PORT, DEFAULT_PROXY_PORT); + } + + public static void putProxyPort(int value) { + putInt(KEY_PROXY_PORT, value); + } + /******************** ****** Guide ********************/ diff --git a/app/src/main/java/com/hippo/ehviewer/preference/HatHProxyPreference.java b/app/src/main/java/com/hippo/ehviewer/preference/ProxyPreference.java similarity index 58% rename from app/src/main/java/com/hippo/ehviewer/preference/HatHProxyPreference.java rename to app/src/main/java/com/hippo/ehviewer/preference/ProxyPreference.java index 02e1dd3f7..6a25f658e 100644 --- a/app/src/main/java/com/hippo/ehviewer/preference/HatHProxyPreference.java +++ b/app/src/main/java/com/hippo/ehviewer/preference/ProxyPreference.java @@ -20,64 +20,71 @@ import android.annotation.SuppressLint; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; -import android.support.annotation.Nullable; import android.support.design.widget.TextInputLayout; import android.support.v7.app.AlertDialog; -import android.support.v7.widget.SwitchCompat; +import android.text.TextUtils; import android.util.AttributeSet; import android.view.View; import android.widget.EditText; - +import android.widget.Spinner; +import com.hippo.ehviewer.EhApplication; +import com.hippo.ehviewer.EhProxySelector; import com.hippo.ehviewer.R; import com.hippo.ehviewer.Settings; import com.hippo.network.InetValidator; import com.hippo.preference.DialogPreference; +import com.hippo.yorozuya.MathUtils; import com.hippo.yorozuya.ViewUtils; -public class HatHProxyPreference extends DialogPreference implements View.OnClickListener { +public class ProxyPreference extends DialogPreference implements View.OnClickListener { - @Nullable - private SwitchCompat mEnable; - @Nullable + private Spinner mType; private TextInputLayout mIpInputLayout; - @Nullable private EditText mIp; - @Nullable private TextInputLayout mPortInputLayout; - @Nullable private EditText mPort; - @Nullable - private TextInputLayout mPasskeyInputLayout; - @Nullable - private EditText mPasskey; - public HatHProxyPreference(Context context) { + public ProxyPreference(Context context) { super(context); init(); } - public HatHProxyPreference(Context context, AttributeSet attrs) { + public ProxyPreference(Context context, AttributeSet attrs) { super(context, attrs); init(); } - public HatHProxyPreference(Context context, AttributeSet attrs, int defStyleAttr) { + public ProxyPreference(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { - setDialogLayoutResource(R.layout.preference_dialog_hath_proxy); - updateSummary(Settings.getHathProxy(), Settings.getHathIp(), Settings.getHathPort()); + setDialogLayoutResource(R.layout.preference_dialog_proxy); + updateSummary(Settings.getProxyType(), Settings.getProxyIp(), Settings.getProxyPort()); } - private void updateSummary(boolean hathProxy, String hathIp, int hathPort) { - if (InetValidator.isValidInet4Address(hathIp) && InetValidator.isValidInetPort(hathPort)) { + private String getProxyTypeText(Context context, int type) { + String[] array = context.getResources().getStringArray(R.array.proxy_types); + return array[MathUtils.clamp(type, 0, array.length - 1)]; + } + + private void updateSummary(int type, String ip, int port) { + if ((type == EhProxySelector.TYPE_HTTP || type == EhProxySelector.TYPE_SOCKS) + && (TextUtils.isEmpty(ip) || !InetValidator.isValidInetPort(port)) ) { + type = EhProxySelector.TYPE_SYSTEM; + } + + if (type == EhProxySelector.TYPE_HTTP || type == EhProxySelector.TYPE_SOCKS) { Context context = getContext(); - setSummary(context.getString(R.string.settings_eh_hath_proxy_summary_1, - context.getString(hathProxy ? R.string.enabled : R.string.disabled), hathIp, hathPort)); + setSummary(context.getString(R.string.settings_advanced_proxy_summary_1, + getProxyTypeText(context, type), + ip, + port)); } else { - setSummary(R.string.settings_eh_hath_proxy_summary_2); + Context context = getContext(); + setSummary(context.getString(R.string.settings_advanced_proxy_summary_2, + getProxyTypeText(context, type))); } } @@ -94,73 +101,63 @@ public class HatHProxyPreference extends DialogPreference implements View.OnClic dialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(this); - mEnable = (SwitchCompat) ViewUtils.$$(dialog, R.id.enable); + mType = (Spinner) ViewUtils.$$(dialog, R.id.type); mIpInputLayout = (TextInputLayout) ViewUtils.$$(dialog, R.id.ip_input_layout); mIp = (EditText) ViewUtils.$$(dialog, R.id.ip); mPortInputLayout = (TextInputLayout) ViewUtils.$$(dialog, R.id.port_input_layout); mPort = (EditText) ViewUtils.$$(dialog, R.id.port); - mPasskeyInputLayout = (TextInputLayout) ViewUtils.$$(dialog, R.id.passkey_input_layout); - mPasskey = (EditText) ViewUtils.$$(dialog, R.id.passkey); - mEnable.setChecked(Settings.getHathProxy()); - String ip = Settings.getHathIp(); - if (!InetValidator.isValidInet4Address(ip)) { - ip = null; - } + int type = Settings.getProxyType(); + String[] array = getContext().getResources().getStringArray(R.array.proxy_types); + mType.setSelection(MathUtils.clamp(type, 0, array.length)); + + mIp.setText(Settings.getProxyIp()); + String portString; - int port = Settings.getHathPort(); + int port = Settings.getProxyPort(); if (!InetValidator.isValidInetPort(port)) { portString = null; } else { - portString = Integer.toString(Settings.getHathPort()); + portString = Integer.toString(port); } - mIp.setText(ip); mPort.setText(portString); - mPasskey.setText(Settings.getHathPasskey()); } @Override protected void onDialogClosed(boolean positiveResult) { super.onDialogClosed(positiveResult); - mEnable = null; + mType = null; mIpInputLayout = null; mIp = null; mPortInputLayout = null; mPort = null; - mPasskeyInputLayout = null; - mPasskey = null; } @Override public void onClick(View v) { Dialog dialog = getDialog(); Context context = getContext(); - if (null == dialog || null == context || null == mEnable || + if (null == dialog || null == context || null == mType || null == mIpInputLayout || null == mIp || - null == mPortInputLayout || null == mPort || - null == mPasskeyInputLayout || null == mPasskey) { + null == mPortInputLayout || null == mPort) { return; } - boolean enable = mEnable.isChecked(); + int type = mType.getSelectedItemPosition(); String ip = mIp.getText().toString().trim(); if (ip.isEmpty()) { - if (enable) { + if (type == EhProxySelector.TYPE_HTTP || type == EhProxySelector.TYPE_SOCKS) { mIpInputLayout.setError(context.getString(R.string.text_is_empty)); return; } - } else if (!InetValidator.isValidInet4Address(ip)) { - mIpInputLayout.setError(context.getString(R.string.domain_not_supported)); - return; - } else { - mIpInputLayout.setError(null); } + mIpInputLayout.setError(null); int port; String portString = mPort.getText().toString().trim(); if (portString.isEmpty()) { - if (enable) { + if (type == EhProxySelector.TYPE_HTTP || type == EhProxySelector.TYPE_SOCKS) { mPortInputLayout.setError(context.getString(R.string.text_is_empty)); return; } else { @@ -173,19 +170,19 @@ public class HatHProxyPreference extends DialogPreference implements View.OnClic port = -1; } if (!InetValidator.isValidInetPort(port)) { - mPortInputLayout.setError(context.getString(R.string.invalid_port)); + mPortInputLayout.setError(context.getString(R.string.proxy_invalid_port)); return; } } + mPortInputLayout.setError(null); - String passkey = mPasskey.getText().toString(); + Settings.putProxyType(type); + Settings.putProxyIp(ip); + Settings.putProxyPort(port); - Settings.putHathProxy(enable); - Settings.putHathIp(ip); - Settings.putHathPort(port); - Settings.putHathPasskey(passkey); + updateSummary(type, ip, port); - updateSummary(enable, ip, port); + EhApplication.getEhProxySelector(getContext()).updateProxy(); dialog.dismiss(); } diff --git a/app/src/main/res/layout/preference_dialog_hath_proxy.xml b/app/src/main/res/layout/preference_dialog_proxy.xml similarity index 72% rename from app/src/main/res/layout/preference_dialog_hath_proxy.xml rename to app/src/main/res/layout/preference_dialog_proxy.xml index 8aeb5abc1..fd56ca6a4 100644 --- a/app/src/main/res/layout/preference_dialog_hath_proxy.xml +++ b/app/src/main/res/layout/preference_dialog_proxy.xml @@ -21,20 +21,22 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="?attr/dialogPreferredPadding" - android:paddingTop="@dimen/abc_dialog_padding_top_material" + android:paddingTop="18dp" android:paddingRight="?attr/dialogPreferredPadding"> - + android:paddingTop="8dp" + android:paddingBottom="8dp" + android:entries="@array/proxy_types"/> + android:hint="@string/proxy_host_or_ip"> + android:hint="@string/proxy_port"> - - - - - - diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index d89c7f9d6..79b5ec205 100755 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -317,9 +317,6 @@ Galerie von den ausgeschlossenen Sprachen werden in der Galerieliste und der Suchen versteckt Ausgeschlossene Namensraum-Etiketten Galerie in der ausgeschlossenen Namensraum werden vom Standard-Etikett-Suchen versteckt - H@H Proxy - %1$s %2$s:%3$d - Nicht festgelegt Japanische Titel anzeigen Versuchen, japanische Titel anzuzeigen. Es wird länger dauern, Galerieliste zu laden. Standardtitel anzeigen. Sie sind oft in Englisch. @@ -393,6 +390,9 @@ Speichern gescheitert Protokolldatei wurde auf %s gespeichert. Downloadpfadzwischenspeicher löschen + Proxy + %1$s %2$s:%3$d + %1$s Open Source-Lizenzen Verzeichnis auswählen Das Verzeichnis ist nicht beschreibbar @@ -467,14 +467,12 @@ Auf Update überprüfen Beta-Version testen Beta-Version kann funktionieren möglicherweise nicht - Aktivieren - Aktiviert - Nicht aktiviert - IP - Port - Schlüssel - Der Domain ist nicht unterstützt. - Ungültiger Port + Aktivieren + Aktiviert + Nicht aktiviert + Port + Der Domain ist nicht unterstützt. + Ungültiger Port Datenverzeichnis konnte geladen werden Keine Daten gefunden Datei kann nicht gelesen werden diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 7d0467814..b1a4c2c76 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -366,9 +366,6 @@ Ocultar galerías en ciertos idiomas de la lista de galerías y búsquedas Excluir etiquetas espacios de nombres Excluir ciertos espacios de nombres de una búsqueda de etiquetas por defecto - H@H proxy - %1$s %2$s:%3$d - Sin establecer Mostrar títulos en japonés Intentar mostrar títulos en japonés. Tomará más tiempo en cargar la lista de galerías Mostrar títulos por defecto, usualmente es en inglés @@ -453,6 +450,9 @@ Borrar vistas previas, galerías, información y caché de memoria Tamaño del caché (archivos temporales) Idioma de la aplicación + Proxy + %1$s %2$s:%3$d + %1$s Protección por patrón No se ha configurado la protección por patrón La protección por patrón ha sido configurado @@ -480,13 +480,11 @@ Canal de versiones de prueba Las versiones de prueba podrían tener errores - Habilitar - Habilitado - IP - Puerto - Clave Maestra - Dominio no soportado - Puerto Invalido + Habilitar + Habilitado + Puerto + Dominio no soportado + Puerto Invalido No se puede obtener el directorio de datos No se pueden encuentran datos @@ -606,7 +604,6 @@ Eliminar Seleccionar directorio No se puede escribir en el directorio - Deshabilitado Descarga fallida Descarga en pausa La contraseña no puede estar vacía diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index fa095ff01..7bc2cfe8a 100755 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -391,9 +391,6 @@ Ne pas afficher les galerie des langues spécifiées sur la liste de galerie et le résultat de recherche Espaces de nom de tag exclues Exclure espaces de nom spécifiées de une recherche de tag par défaut - H@H proxy - %1$s %2$s:%3$d - Rien Montrer les titres japonais Essayer de charger les titres japonais. Il prend plus de temps pour charger la liste des galeries. Montrer les titres par défaut. Ils sont souvent en anglais. @@ -476,6 +473,9 @@ Vider le cache du stockage Effacer le cache des miniatures et des informations galeries Taille du cache pour la lecture + Proxy + %1$s %2$s:%3$d + %1$s Modéle de déverrouillage Aucun modéle de déverrouillage Modéle de déverrouillage défini @@ -504,14 +504,12 @@ Chaîne de mises à jour beta Versions beta riquent de ne pas fonctionner correctement sur votre appareil - Activer - Activé - Non activé - IP - Port - Clé de passe - Le domaine n\'est pas compatible - Port invalide + Activer + Activé + Non activé + Port + Le domaine n\'est pas compatible + Port invalide Échec d\'obtention du répertoire données Aucune donnée trouvée diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 0b419129e..e5325ddf2 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -389,9 +389,6 @@ 指定したタグセットをデフォルト検索から除外 言語を除外 指定した言語のギャラリーをホームページと検索から隠す - H@H プロキシ - %1$s %2$s:%3$d - 未設定 日本語タイトルを表示 日本語タイトルを表示しようとします。有効にすると、ギャラリーリストを取得するのにもっと時間がかかることがあります デフォルトのタイトルを表示します。多くの場合は英語のタイトルです。 @@ -470,6 +467,9 @@ メモリキャッシュをクリア サムネイルとギャラリー情報のメモリキャッシュをクリア 閲覧キャッシュのサイズ + プロキシ + %1$s %2$s:%3$d + %1$s パターン保護 パターン保護は設定されていません パターン保護は設定されています @@ -525,14 +525,12 @@ お待ちください - 有効化 - 有効化済み - 無効 - IP - ポート - パスキー - ドメイン名には対応していません - 無効なポート + 有効化 + 有効化済み + 無効 + ポート + ドメイン名には対応していません + 無効なポート データフォルダを取得できませんでした データが見つかりません diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index a6adaffac..4e950a1dc 100755 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -383,9 +383,6 @@ 갤러리 목록과 검색에서 특정 언어 숨기기 제외할 태그 네임스페이스 기본 태그 검색에서 특정 네임스페이스 제외 - H@H 프록시 - %1$s %2$s:%3$d - 없음 일본어 제목 표시 가능하면 일본어 제목을 표시합니다. 갤러리 목록을 불러오는 데 시간이 좀 더 걸립니다. 기본 제목을 표시합니다. 대부분 영어로 표시됩니다. @@ -469,6 +466,9 @@ 섬네일, 갤러리 정보 메모리 캐시 삭제 읽기 캐시 크기 앱 언어 (Language) + 프록시 + %1$s %2$s:%3$d + %1$s 앱 내장 hosts.txt 앱에 내장된 호스트-IP 지정 규칙을 사용합니다.\n대신 사용자 지정 hosts.txt 파일을 사용할 수도 있습니다. 사용자 지정 hosts.txt @@ -500,14 +500,12 @@ 베타 업데이트 채널 베타 버전은 사용자의 기기에서 정상적으로 작동하지 않을 수 있습니다. - 사용 - 사용함 - 사용 안 함 - IP - 포트 - 암호 - 지원하지 않는 도메인입니다. - 잘못된 포트입니다. + 사용 + 사용함 + 사용 안 함 + 포트 + 지원하지 않는 도메인입니다. + 잘못된 포트입니다. 데이터 디렉터리를 찾을 수 없습니다. 데이터를 가져올 수 없습니다. diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 69a1f9f5a..d1726b9df 100755 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -425,9 +425,6 @@ 在默认搜索中排除指定标签组 排除语言 在主页与搜索中隐藏指定语言的画廊 - H@H - %1$s %2$s:%3$d - 未设置 显示日文标题 尝试显示日文标题。这会使获取画廊列表花费更多时间 显示默认标题。一般是英文标题 @@ -517,6 +514,9 @@ 清理缩略图、画廊信息的内存缓存 阅读缓存大小 App 界面语言 + 代理 + %1$s %2$s:%3$d + %1$s 内置 hosts.txt 应用提供的主机到IP的映射\n可被自定义 hosts.txt 覆盖 自定义 hosts.txt @@ -584,14 +584,15 @@ 请稍候 - 启用 - 已启用 - 未启用 - IP - 端口 - 密钥 - 不支持域名 - 无效的端口 + 启用 + 已启用 + 未启用 + 直接连接 + 系统代理 + 主机或 IP + 端口 + 不支持域名 + 无效的端口 无法获取数据文件夹 找不到任何数据 diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml index e887e8ff6..2d99e782b 100755 --- a/app/src/main/res/values-zh-rHK/strings.xml +++ b/app/src/main/res/values-zh-rHK/strings.xml @@ -424,9 +424,6 @@ 在默認搜索中排除指定標籤組 排除語言 在主頁與搜索中隱藏指定語言的畫廊 - H@H - %1$s %2$s:%3$d - 未設置 顯示日文標題 嘗試顯示日文標題。這會使獲取畫廊列表花費更多時間 顯示默認標題。一般是英文標題 @@ -515,6 +512,9 @@ 清理內存緩存 清理縮略圖、畫廊信息的內存緩存 閲讀緩存大小 + 代理 + %1$s %2$s:%3$d + %1$s App 界面語言 內置 hosts.txt 應用提供的主機到IP的映射\n可被自定義 hosts.txt 覆蓋 @@ -583,14 +583,15 @@ 請稍候 - 啟用 - 已啟用 - 未啟用 - IP - 端口 - 密鑰 - 不支持域名 - 無效的端口 + 啟用 + 已啟用 + 未啟用 + 直接連接 + 系統代理 + 主機或 IP + 端口 + 不支持域名 + 無效的端口 無法獲取數據文件夾 找不到任何數據 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index f937acd26..772f877af 100755 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -424,9 +424,6 @@ 在預設標籤搜尋中排除特定的標籤命名空間 排除語言 在首頁與搜尋中隱藏指定語言的圖庫 - H@H - %1$s %2$s:%3$d - 無 顯示日文標題 嘗試顯示日文標題。這會使取得圖庫列表時間增加 顯示預設的標題。通常是英文的 @@ -516,6 +513,9 @@ 清除縮圖、圖庫詳細資料的記憶體快取 閱讀快取大小 App 介面語言 + 代理 + %1$s %2$s:%3$d + %1$s 內建 hosts.txt 應用提供的主機到IP的對映\n可被自定義 hosts.txt 覆蓋 自定義 hosts.txt @@ -583,14 +583,15 @@ 請稍候 - 啟用 - 已啟用 - 未啟用 - IP - 通訊埠 - 金鑰 - 不支援的域名 - 無效的通訊埠 + 啟用 + 已啟用 + 未啟用 + 直接連線 + 系統代理 + 主機或 IP + 通訊埠 + 不支援的域名 + 無效的通訊埠 無法取得檔案資料夾 找不到任何資料 diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 7bc4f88a3..819c3c6bb 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -15,7 +15,7 @@ ~ limitations under the License. --> - + @string/settings_eh_theme_light @@ -255,8 +255,15 @@ zh-TW - + @null + + @string/proxy_direct + @string/proxy_system + HTTP + SOCKS + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d35bca9c1..a75696f01 100755 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -468,9 +468,6 @@ Hide galleries in certain languages from the gallery list and searches Excluded tag namespaces Exclude certain namespaces from a default tag search - H@H proxy - %1$s %2$s:%3$d - None Show Japanese title Attempt to show Japanese title. It takes more time to get gallery list Show default titles, which are usually in English. @@ -560,6 +557,9 @@ Clear thumb, gallery info memory cache Read cache size App language + Proxy + %1$s %2$s:%3$d + %1$s Built-in hosts.txt Apply the built-in host-to-IP mapping provided by the app.\nIt can be overridden by custom hosts.txt. Custom hosts.txt @@ -601,14 +601,15 @@ Beta update channel Beta versions may contain unsolved bugs. - Enable - Enabled - Disabled - IP - Port - Passkey - Domain is not supported - Invalid port + Enable + Enabled + Disabled + Direct + System Proxy + Host or IP + Port + Domain is not supported + Invalid port Can\'t get data dir Can\'t find any data diff --git a/app/src/main/res/xml/advanced_settings.xml b/app/src/main/res/xml/advanced_settings.xml index 76b357441..1d028d918 100644 --- a/app/src/main/res/xml/advanced_settings.xml +++ b/app/src/main/res/xml/advanced_settings.xml @@ -49,13 +49,17 @@ android:defaultValue="160"/> + xmlns:app="http://schemas.android.com/apk/res-auto" + android:key="app_language" + android:title="@string/settings_advanced_app_language_title" + android:summary="%s" + app:entries="@array/app_language_entries" + app:entryValues="@array/app_language_entry_values" + android:defaultValue="system"/> + +