diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml
index 3b2ee429f..ec201402c 100644
--- a/src/main/AndroidManifest.xml
+++ b/src/main/AndroidManifest.xml
@@ -249,6 +249,11 @@
+
+
{
+ proxyGroup.setVisibility(isChecked? View.VISIBLE : View.GONE);
+ });
+ proxySwitch.setChecked(DcHelper.getInt(this, CONFIG_SOCKS5_ENABLED) == 1);
+
+ TextInputEditText proxyHostInput = findViewById(R.id.proxy_host_text);
+ proxyHostInput.setOnFocusChangeListener((view, focused) -> focusListener(view, focused, VerificationType.SERVER));
+ proxyHostInput.setText(DcHelper.get(this, CONFIG_SOCKS5_HOST));
+
+ TextInputEditText proxyPortInput = findViewById(R.id.proxy_port_text);
+ proxyPortInput.setOnFocusChangeListener((view, focused) -> focusListener(view, focused, VerificationType.PORT));
+ proxyPortInput.setText(DcHelper.get(this, CONFIG_SOCKS5_PORT));
+
+ TextInputEditText proxyUserInput = findViewById(R.id.proxy_user_text);
+ proxyUserInput.setText(DcHelper.get(this, CONFIG_SOCKS5_USER));
+
+ TextInputEditText proxyPasswordInput = findViewById(R.id.proxy_password_text);
+ proxyPasswordInput.setText(DcHelper.get(this, CONFIG_SOCKS5_PASSWORD));
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ dynamicTheme.onResume(this);
+ }
+
+ public boolean onOptionsItemSelected(MenuItem item) {
+ int id = item.getItemId();
+ if (id == android.R.id.home) {
+ finish();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ saveConfig();
+ }
+
+ private void focusListener(View view, boolean focused, VerificationType type) {
+
+ if (!focused) {
+ TextInputEditText inputEditText = (TextInputEditText) view;
+ switch (type) {
+ case SERVER:
+ verifyServer(inputEditText);
+ break;
+ case PORT:
+ verifyPort(inputEditText);
+ break;
+ }
+ }
+ }
+
+ private void verifyServer(TextInputEditText view) {
+ String server = view.getText().toString();
+ if (!TextUtils.isEmpty(server) && !Patterns.DOMAIN_NAME.matcher(server).matches()
+ && !Patterns.IP_ADDRESS.matcher(server).matches()
+ && !Patterns.WEB_URL.matcher(server).matches()
+ && !"localhost".equals(server)) {
+ view.setError(getString(R.string.login_error_server));
+ }
+ }
+
+ private void verifyPort(TextInputEditText view) {
+ String portString = view.getText().toString();
+ if (!portString.isEmpty()) {
+ String error = getString(R.string.login_error_port);
+ try {
+ int port = Integer.valueOf(portString);
+ if (port < 1 || port > 65535) {
+ view.setError(error);
+ }
+ } catch (NumberFormatException exception) {
+ view.setError(error);
+ }
+ }
+ }
+
+ private void saveConfig() {
+ DcHelper.getContext(this).setConfigInt(CONFIG_SOCKS5_ENABLED, proxySwitch.isChecked()? 1 : 0);
+ setConfig(R.id.proxy_host_text, CONFIG_SOCKS5_HOST, true);
+ setConfig(R.id.proxy_port_text, CONFIG_SOCKS5_PORT, true);
+ setConfig(R.id.proxy_user_text, CONFIG_SOCKS5_USER, true);
+ setConfig(R.id.proxy_password_text, CONFIG_SOCKS5_PASSWORD, false);
+ }
+
+ private void setConfig(@IdRes int viewId, String configTarget, boolean doTrim) {
+ TextInputEditText view = findViewById(viewId);
+ String value = view.getText().toString();
+ if(doTrim) {
+ value = value.trim();
+ }
+ DcHelper.getContext(this).setConfig(configTarget, value.isEmpty()? null : value);
+ }
+
+}
diff --git a/src/main/res/layout/proxy_settings_activity.xml b/src/main/res/layout/proxy_settings_activity.xml
new file mode 100644
index 000000000..d3660855e
--- /dev/null
+++ b/src/main/res/layout/proxy_settings_activity.xml
@@ -0,0 +1,128 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/res/menu/instant_onboarding_menu.xml b/src/main/res/menu/instant_onboarding_menu.xml
new file mode 100644
index 000000000..c30ec587c
--- /dev/null
+++ b/src/main/res/menu/instant_onboarding_menu.xml
@@ -0,0 +1,15 @@
+
+
+
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index 17bc0caff..9ae997edb 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -604,6 +604,8 @@
SMTP Port
SMTP Security
Authorization Method
+ Proxy Settings
+ Use Proxy
SOCKS5
Use SOCKS5