mirror of
https://github.com/deltachat/deltachat-android.git
synced 2025-10-05 10:39:24 +02:00
use new proxy_url list API (#3292)
This commit is contained in:
parent
8aa615157a
commit
bc6d676fcd
15 changed files with 544 additions and 299 deletions
|
@ -249,7 +249,7 @@
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity android:name=".ProxySettingsActivity"
|
<activity android:name=".proxy.ProxySettingsActivity"
|
||||||
android:label="@string/proxy_settings"
|
android:label="@string/proxy_settings"
|
||||||
android:windowSoftInputMode="stateHidden"
|
android:windowSoftInputMode="stateHidden"
|
||||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
|
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
|
||||||
|
|
|
@ -56,6 +56,7 @@ public class DcContext {
|
||||||
public final static int DC_QR_BACKUP = 251;
|
public final static int DC_QR_BACKUP = 251;
|
||||||
public final static int DC_QR_BACKUP2 = 252;
|
public final static int DC_QR_BACKUP2 = 252;
|
||||||
public final static int DC_QR_WEBRTC = 260;
|
public final static int DC_QR_WEBRTC = 260;
|
||||||
|
public final static int DC_QR_PROXY = 271;
|
||||||
public final static int DC_QR_ADDR = 320;
|
public final static int DC_QR_ADDR = 320;
|
||||||
public final static int DC_QR_TEXT = 330;
|
public final static int DC_QR_TEXT = 330;
|
||||||
public final static int DC_QR_URL = 332;
|
public final static int DC_QR_URL = 332;
|
||||||
|
|
|
@ -20,7 +20,7 @@ import static org.thoughtcrime.securesms.ConversationActivity.CHAT_ID_EXTRA;
|
||||||
import static org.thoughtcrime.securesms.ConversationActivity.STARTING_POSITION_EXTRA;
|
import static org.thoughtcrime.securesms.ConversationActivity.STARTING_POSITION_EXTRA;
|
||||||
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_ADDRESS;
|
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_ADDRESS;
|
||||||
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_SERVER_FLAGS;
|
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_SERVER_FLAGS;
|
||||||
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_SOCKS5_ENABLED;
|
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_PROXY_URL;
|
||||||
import static org.thoughtcrime.securesms.util.RelayUtil.acquireRelayMessageContent;
|
import static org.thoughtcrime.securesms.util.RelayUtil.acquireRelayMessageContent;
|
||||||
import static org.thoughtcrime.securesms.util.RelayUtil.getDirectSharingChatId;
|
import static org.thoughtcrime.securesms.util.RelayUtil.getDirectSharingChatId;
|
||||||
import static org.thoughtcrime.securesms.util.RelayUtil.getSharedTitle;
|
import static org.thoughtcrime.securesms.util.RelayUtil.getSharedTitle;
|
||||||
|
@ -64,6 +64,7 @@ import org.thoughtcrime.securesms.connect.DcHelper;
|
||||||
import org.thoughtcrime.securesms.connect.DirectShareUtil;
|
import org.thoughtcrime.securesms.connect.DirectShareUtil;
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||||
import org.thoughtcrime.securesms.permissions.Permissions;
|
import org.thoughtcrime.securesms.permissions.Permissions;
|
||||||
|
import org.thoughtcrime.securesms.proxy.ProxySettingsActivity;
|
||||||
import org.thoughtcrime.securesms.qr.QrActivity;
|
import org.thoughtcrime.securesms.qr.QrActivity;
|
||||||
import org.thoughtcrime.securesms.qr.QrCodeHandler;
|
import org.thoughtcrime.securesms.qr.QrCodeHandler;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
|
@ -361,7 +362,7 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
|
||||||
if (!isRelayingMessageContent(this)) {
|
if (!isRelayingMessageContent(this)) {
|
||||||
inflater.inflate(R.menu.text_secure_normal, menu);
|
inflater.inflate(R.menu.text_secure_normal, menu);
|
||||||
menu.findItem(R.id.menu_global_map).setVisible(Prefs.isLocationStreamingEnabled(this));
|
menu.findItem(R.id.menu_global_map).setVisible(Prefs.isLocationStreamingEnabled(this));
|
||||||
menu.findItem(R.id.menu_proxy_settings).setVisible(DcHelper.getInt(this, CONFIG_SOCKS5_ENABLED) == 1);
|
menu.findItem(R.id.menu_proxy_settings).setVisible(!TextUtils.isEmpty(DcHelper.get(this, CONFIG_PROXY_URL)));
|
||||||
}
|
}
|
||||||
|
|
||||||
super.onPrepareOptionsMenu(menu);
|
super.onPrepareOptionsMenu(menu);
|
||||||
|
|
|
@ -48,6 +48,7 @@ import org.thoughtcrime.securesms.mms.GlideApp;
|
||||||
import org.thoughtcrime.securesms.permissions.Permissions;
|
import org.thoughtcrime.securesms.permissions.Permissions;
|
||||||
import org.thoughtcrime.securesms.profiles.AvatarHelper;
|
import org.thoughtcrime.securesms.profiles.AvatarHelper;
|
||||||
import org.thoughtcrime.securesms.profiles.ProfileMediaConstraints;
|
import org.thoughtcrime.securesms.profiles.ProfileMediaConstraints;
|
||||||
|
import org.thoughtcrime.securesms.proxy.ProxySettingsActivity;
|
||||||
import org.thoughtcrime.securesms.qr.RegistrationQrActivity;
|
import org.thoughtcrime.securesms.qr.RegistrationQrActivity;
|
||||||
import org.thoughtcrime.securesms.scribbles.ScribbleActivity;
|
import org.thoughtcrime.securesms.scribbles.ScribbleActivity;
|
||||||
import org.thoughtcrime.securesms.util.Prefs;
|
import org.thoughtcrime.securesms.util.Prefs;
|
||||||
|
|
|
@ -1,160 +0,0 @@
|
||||||
package org.thoughtcrime.securesms;
|
|
||||||
|
|
||||||
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_SOCKS5_ENABLED;
|
|
||||||
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_SOCKS5_HOST;
|
|
||||||
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_SOCKS5_PASSWORD;
|
|
||||||
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_SOCKS5_PORT;
|
|
||||||
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_SOCKS5_USER;
|
|
||||||
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.util.Patterns;
|
|
||||||
import android.view.MenuItem;
|
|
||||||
import android.view.View;
|
|
||||||
|
|
||||||
import androidx.annotation.IdRes;
|
|
||||||
import androidx.appcompat.app.ActionBar;
|
|
||||||
import androidx.appcompat.widget.SwitchCompat;
|
|
||||||
import androidx.constraintlayout.widget.Group;
|
|
||||||
|
|
||||||
import com.b44t.messenger.DcContext;
|
|
||||||
import com.google.android.material.textfield.TextInputEditText;
|
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.connect.DcHelper;
|
|
||||||
import org.thoughtcrime.securesms.util.DynamicTheme;
|
|
||||||
|
|
||||||
public class ProxySettingsActivity extends BaseActionBarActivity {
|
|
||||||
|
|
||||||
private enum VerificationType {
|
|
||||||
SERVER,
|
|
||||||
PORT,
|
|
||||||
}
|
|
||||||
|
|
||||||
private final DynamicTheme dynamicTheme = new DynamicTheme();
|
|
||||||
|
|
||||||
private SwitchCompat proxySwitch;
|
|
||||||
private Group proxyGroup;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate(Bundle bundle) {
|
|
||||||
super.onCreate(bundle);
|
|
||||||
dynamicTheme.onCreate(this);
|
|
||||||
setContentView(R.layout.proxy_settings_activity);
|
|
||||||
|
|
||||||
ActionBar actionBar = getSupportActionBar();
|
|
||||||
if (actionBar != null) {
|
|
||||||
actionBar.setTitle(R.string.proxy_settings);
|
|
||||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
proxyGroup = findViewById(R.id.proxy_group);
|
|
||||||
|
|
||||||
proxySwitch = findViewById(R.id.proxy_switch);
|
|
||||||
proxySwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPause() {
|
|
||||||
super.onPause();
|
|
||||||
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() {
|
|
||||||
DcContext dcContext = DcHelper.getContext(this);
|
|
||||||
dcContext.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);
|
|
||||||
dcContext.stopIo();
|
|
||||||
dcContext.startIo();
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -12,11 +12,7 @@ import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_SEND_SECURITY;
|
||||||
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_SEND_SERVER;
|
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_SEND_SERVER;
|
||||||
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_SEND_USER;
|
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_SEND_USER;
|
||||||
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_SERVER_FLAGS;
|
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_SERVER_FLAGS;
|
||||||
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_SOCKS5_ENABLED;
|
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_PROXY_ENABLED;
|
||||||
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_SOCKS5_HOST;
|
|
||||||
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_SOCKS5_PASSWORD;
|
|
||||||
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_SOCKS5_PORT;
|
|
||||||
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_SOCKS5_USER;
|
|
||||||
import static org.thoughtcrime.securesms.connect.DcHelper.getContext;
|
import static org.thoughtcrime.securesms.connect.DcHelper.getContext;
|
||||||
import static org.thoughtcrime.securesms.service.IPCAddAccountsService.ACCOUNT_DATA;
|
import static org.thoughtcrime.securesms.service.IPCAddAccountsService.ACCOUNT_DATA;
|
||||||
|
|
||||||
|
@ -59,6 +55,7 @@ import com.google.android.material.textfield.TextInputEditText;
|
||||||
import org.thoughtcrime.securesms.connect.DcEventCenter;
|
import org.thoughtcrime.securesms.connect.DcEventCenter;
|
||||||
import org.thoughtcrime.securesms.connect.DcHelper;
|
import org.thoughtcrime.securesms.connect.DcHelper;
|
||||||
import org.thoughtcrime.securesms.permissions.Permissions;
|
import org.thoughtcrime.securesms.permissions.Permissions;
|
||||||
|
import org.thoughtcrime.securesms.proxy.ProxySettingsActivity;
|
||||||
import org.thoughtcrime.securesms.util.DynamicTheme;
|
import org.thoughtcrime.securesms.util.DynamicTheme;
|
||||||
import org.thoughtcrime.securesms.util.IntentUtils;
|
import org.thoughtcrime.securesms.util.IntentUtils;
|
||||||
import org.thoughtcrime.securesms.util.Util;
|
import org.thoughtcrime.securesms.util.Util;
|
||||||
|
@ -162,7 +159,7 @@ public class RegistrationActivity extends BaseActionBarActivity implements DcEve
|
||||||
String strVal;
|
String strVal;
|
||||||
int intVal;
|
int intVal;
|
||||||
|
|
||||||
intVal = DcHelper.getInt(this, CONFIG_SOCKS5_ENABLED);
|
intVal = DcHelper.getInt(this, CONFIG_PROXY_ENABLED);
|
||||||
proxySwitch.setChecked(intVal == 1);
|
proxySwitch.setChecked(intVal == 1);
|
||||||
expandAdvanced = expandAdvanced || intVal == 1;
|
expandAdvanced = expandAdvanced || intVal == 1;
|
||||||
|
|
||||||
|
@ -260,7 +257,7 @@ public class RegistrationActivity extends BaseActionBarActivity implements DcEve
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
dynamicTheme.onResume(this);
|
dynamicTheme.onResume(this);
|
||||||
proxySwitch.setChecked(DcHelper.getInt(this, CONFIG_SOCKS5_ENABLED) == 1);
|
proxySwitch.setChecked(DcHelper.getInt(this, CONFIG_PROXY_ENABLED) == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showLog() {
|
private void showLog() {
|
||||||
|
|
|
@ -72,11 +72,8 @@ public class DcHelper {
|
||||||
public static final String CONFIG_SHOW_EMAILS = "show_emails";
|
public static final String CONFIG_SHOW_EMAILS = "show_emails";
|
||||||
public static final String CONFIG_MEDIA_QUALITY = "media_quality";
|
public static final String CONFIG_MEDIA_QUALITY = "media_quality";
|
||||||
public static final String CONFIG_WEBRTC_INSTANCE = "webrtc_instance";
|
public static final String CONFIG_WEBRTC_INSTANCE = "webrtc_instance";
|
||||||
public static final String CONFIG_SOCKS5_ENABLED = "socks5_enabled";
|
public static final String CONFIG_PROXY_ENABLED = "proxy_enabled";
|
||||||
public static final String CONFIG_SOCKS5_HOST = "socks5_host";
|
public static final String CONFIG_PROXY_URL = "proxy_url";
|
||||||
public static final String CONFIG_SOCKS5_PORT = "socks5_port";
|
|
||||||
public static final String CONFIG_SOCKS5_USER = "socks5_user";
|
|
||||||
public static final String CONFIG_SOCKS5_PASSWORD = "socks5_password";
|
|
||||||
public static final String CONFIG_VERIFIED_ONE_ON_ONE_CHATS = "verified_one_on_one_chats";
|
public static final String CONFIG_VERIFIED_ONE_ON_ONE_CHATS = "verified_one_on_one_chats";
|
||||||
public static final String CONFIG_WEBXDC_REALTIME_ENABLED = "webxdc_realtime_enabled";
|
public static final String CONFIG_WEBXDC_REALTIME_ENABLED = "webxdc_realtime_enabled";
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ import com.b44t.messenger.rpc.RpcException;
|
||||||
import org.thoughtcrime.securesms.ApplicationPreferencesActivity;
|
import org.thoughtcrime.securesms.ApplicationPreferencesActivity;
|
||||||
import org.thoughtcrime.securesms.ConversationActivity;
|
import org.thoughtcrime.securesms.ConversationActivity;
|
||||||
import org.thoughtcrime.securesms.LogViewActivity;
|
import org.thoughtcrime.securesms.LogViewActivity;
|
||||||
import org.thoughtcrime.securesms.ProxySettingsActivity;
|
import org.thoughtcrime.securesms.proxy.ProxySettingsActivity;
|
||||||
import org.thoughtcrime.securesms.R;
|
import org.thoughtcrime.securesms.R;
|
||||||
import org.thoughtcrime.securesms.RegistrationActivity;
|
import org.thoughtcrime.securesms.RegistrationActivity;
|
||||||
import org.thoughtcrime.securesms.connect.DcEventCenter;
|
import org.thoughtcrime.securesms.connect.DcEventCenter;
|
||||||
|
|
|
@ -0,0 +1,172 @@
|
||||||
|
package org.thoughtcrime.securesms.proxy;
|
||||||
|
|
||||||
|
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_PROXY_ENABLED;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.BaseAdapter;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.b44t.messenger.DcContext;
|
||||||
|
import com.b44t.messenger.DcLot;
|
||||||
|
|
||||||
|
import org.thoughtcrime.securesms.R;
|
||||||
|
import org.thoughtcrime.securesms.connect.DcHelper;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ProxyListAdapter extends BaseAdapter {
|
||||||
|
private enum ProxyState {
|
||||||
|
CONNECTED,
|
||||||
|
CONNECTING,
|
||||||
|
NOT_CONNECTED,
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull private final Context context;
|
||||||
|
@NonNull private final DcContext dcContext;
|
||||||
|
@NonNull private final List<String> proxies = new LinkedList<>();
|
||||||
|
@Nullable private ItemClickListener itemClickListener;
|
||||||
|
@Nullable private ProxyState proxyState;
|
||||||
|
@Nullable private String selectedProxy;
|
||||||
|
|
||||||
|
public ProxyListAdapter(@NonNull Context context)
|
||||||
|
{
|
||||||
|
this.context = context;
|
||||||
|
this.dcContext = DcHelper.getContext(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCount() {
|
||||||
|
return proxies.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getItem(int position) {
|
||||||
|
return proxies.get(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getItemId(int position) {
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View getView(final int position, View v, final ViewGroup parent) {
|
||||||
|
if (v == null) {
|
||||||
|
v = LayoutInflater.from(context).inflate(R.layout.proxy_list_item, parent, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
TextView host = v.findViewById(R.id.host);
|
||||||
|
TextView protocol = v.findViewById(R.id.protocol);
|
||||||
|
ImageView checkmark = v.findViewById(R.id.checkmark);
|
||||||
|
TextView status = v.findViewById(R.id.status);
|
||||||
|
|
||||||
|
final String proxyUrl = (String)getItem(position);
|
||||||
|
final DcLot qrParsed = dcContext.checkQr(proxyUrl);
|
||||||
|
if (qrParsed.getState() == DcContext.DC_QR_PROXY) {
|
||||||
|
host.setText(qrParsed.getText1());
|
||||||
|
protocol.setText(proxyUrl.split(":", 2)[0]);
|
||||||
|
} else {
|
||||||
|
host.setText(proxyUrl);
|
||||||
|
protocol.setText(R.string.unknown);
|
||||||
|
}
|
||||||
|
if (proxyUrl.equals(selectedProxy)) {
|
||||||
|
checkmark.setVisibility(View.VISIBLE);
|
||||||
|
status.setVisibility(View.VISIBLE);
|
||||||
|
status.setText(getConnectivityString());
|
||||||
|
} else {
|
||||||
|
checkmark.setVisibility(View.GONE);
|
||||||
|
status.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
v.setOnClickListener(view -> {
|
||||||
|
if (itemClickListener != null) {
|
||||||
|
itemClickListener.onItemClick(proxyUrl);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
v.findViewById(R.id.share).setOnClickListener(view -> {
|
||||||
|
if (itemClickListener != null) {
|
||||||
|
itemClickListener.onItemShare(proxyUrl);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
v.findViewById(R.id.delete).setOnClickListener(view -> {
|
||||||
|
if (itemClickListener != null) {
|
||||||
|
itemClickListener.onItemDelete(proxyUrl);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void changeData(String newProxies) {
|
||||||
|
proxies.clear();
|
||||||
|
if (!TextUtils.isEmpty(newProxies)) {
|
||||||
|
Collections.addAll(proxies, newProxies.split("\n"));
|
||||||
|
}
|
||||||
|
selectedProxy = proxies.isEmpty()? null : proxies.get(0);
|
||||||
|
proxyState = null; // to force notifyDataSetChanged() in refreshConnectivity()
|
||||||
|
refreshConnectivity();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSelectedProxy(String proxyUrl) {
|
||||||
|
selectedProxy = proxyUrl;
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getConnectivityString() {
|
||||||
|
if (proxyState == ProxyState.CONNECTED) {
|
||||||
|
return context.getString(R.string.connectivity_connected);
|
||||||
|
}
|
||||||
|
if (proxyState == ProxyState.CONNECTING) {
|
||||||
|
return context.getString(R.string.connectivity_connecting);
|
||||||
|
}
|
||||||
|
return context.getString(R.string.connectivity_not_connected);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void refreshConnectivity() {
|
||||||
|
if (DcHelper.getInt(context, CONFIG_PROXY_ENABLED) != 1) {
|
||||||
|
if (proxyState != ProxyState.NOT_CONNECTED) {
|
||||||
|
proxyState = ProxyState.NOT_CONNECTED;
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int connectivity = dcContext.getConnectivity();
|
||||||
|
if (connectivity >= DcContext.DC_CONNECTIVITY_WORKING) {
|
||||||
|
if (proxyState != ProxyState.CONNECTED) {
|
||||||
|
proxyState = ProxyState.CONNECTED;
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
} else if (connectivity >= DcContext.DC_CONNECTIVITY_CONNECTING) {
|
||||||
|
if (proxyState != ProxyState.CONNECTING) {
|
||||||
|
proxyState = ProxyState.CONNECTING;
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
} else if (proxyState != ProxyState.NOT_CONNECTED) {
|
||||||
|
proxyState = ProxyState.NOT_CONNECTED;
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setItemClickListener(@Nullable ItemClickListener listener) {
|
||||||
|
itemClickListener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ItemClickListener {
|
||||||
|
void onItemClick(String proxyUrl);
|
||||||
|
void onItemShare(String proxyUrl);
|
||||||
|
void onItemDelete(String proxyUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,189 @@
|
||||||
|
package org.thoughtcrime.securesms.proxy;
|
||||||
|
|
||||||
|
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_PROXY_ENABLED;
|
||||||
|
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_PROXY_URL;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.ListView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.appcompat.app.ActionBar;
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
import androidx.appcompat.widget.SwitchCompat;
|
||||||
|
|
||||||
|
import com.b44t.messenger.DcContext;
|
||||||
|
import com.b44t.messenger.DcEvent;
|
||||||
|
import com.b44t.messenger.DcLot;
|
||||||
|
|
||||||
|
import org.thoughtcrime.securesms.BaseActionBarActivity;
|
||||||
|
import org.thoughtcrime.securesms.R;
|
||||||
|
import org.thoughtcrime.securesms.connect.DcEventCenter;
|
||||||
|
import org.thoughtcrime.securesms.connect.DcHelper;
|
||||||
|
import org.thoughtcrime.securesms.util.DynamicTheme;
|
||||||
|
import org.thoughtcrime.securesms.util.Util;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
|
||||||
|
public class ProxySettingsActivity extends BaseActionBarActivity
|
||||||
|
implements ProxyListAdapter.ItemClickListener, DcEventCenter.DcEventDelegate {
|
||||||
|
|
||||||
|
private final DynamicTheme dynamicTheme = new DynamicTheme();
|
||||||
|
private SwitchCompat proxySwitch;
|
||||||
|
private ProxyListAdapter adapter;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle bundle) {
|
||||||
|
super.onCreate(bundle);
|
||||||
|
dynamicTheme.onCreate(this);
|
||||||
|
setContentView(R.layout.proxy_settings_activity);
|
||||||
|
|
||||||
|
ActionBar actionBar = getSupportActionBar();
|
||||||
|
if (actionBar != null) {
|
||||||
|
actionBar.setTitle(R.string.proxy_settings);
|
||||||
|
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
adapter = new ProxyListAdapter(this);
|
||||||
|
adapter.setItemClickListener(this);
|
||||||
|
|
||||||
|
proxySwitch = findViewById(R.id.proxy_switch);
|
||||||
|
proxySwitch.setChecked(DcHelper.getInt(this, CONFIG_PROXY_ENABLED) == 1);
|
||||||
|
proxySwitch.setOnClickListener(l -> {
|
||||||
|
if (proxySwitch.isChecked() && adapter.getCount() == 0) {
|
||||||
|
showAddProxyDialog();
|
||||||
|
} else {
|
||||||
|
DcHelper.set(this, CONFIG_PROXY_ENABLED, proxySwitch.isChecked()? "1" : "0");
|
||||||
|
restartIO();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ListView proxyList = findViewById(R.id.proxy_list);
|
||||||
|
proxyList.setAdapter(adapter);
|
||||||
|
proxyList.addHeaderView(View.inflate(this, R.layout.proxy_list_header, null), null, false);
|
||||||
|
View footer = View.inflate(this, R.layout.proxy_list_footer, null);
|
||||||
|
footer.setOnClickListener(l -> showAddProxyDialog());
|
||||||
|
proxyList.addFooterView(footer);
|
||||||
|
adapter.changeData(DcHelper.get(this, CONFIG_PROXY_URL));
|
||||||
|
DcHelper.getEventCenter(this).addObserver(DcContext.DC_EVENT_CONNECTIVITY_CHANGED, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
dynamicTheme.onResume(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
DcHelper.getEventCenter(this).removeObservers(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 onItemClick(String proxyUrl) {
|
||||||
|
if (DcHelper.getContext(this).setConfigFromQr(proxyUrl)) {
|
||||||
|
restartIO();
|
||||||
|
adapter.setSelectedProxy(proxyUrl);
|
||||||
|
proxySwitch.setChecked(DcHelper.getInt(this, CONFIG_PROXY_ENABLED) == 1);
|
||||||
|
} else {
|
||||||
|
Toast.makeText(this, R.string.proxy_invalid, Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onItemShare(String proxyUrl) {
|
||||||
|
Intent intent = new Intent(Intent.ACTION_SEND);
|
||||||
|
intent.setType("text/plain");
|
||||||
|
intent.putExtra(Intent.EXTRA_TEXT, proxyUrl);
|
||||||
|
startActivity(Intent.createChooser(intent, getString(R.string.chat_share_with_title)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onItemDelete(String proxyUrl) {
|
||||||
|
String host = DcHelper.getContext(this).checkQr(proxyUrl).getText1();
|
||||||
|
AlertDialog dialog = new AlertDialog.Builder(this)
|
||||||
|
.setTitle(R.string.proxy_delete)
|
||||||
|
.setMessage(getString(R.string.proxy_delete_explain, host))
|
||||||
|
.setPositiveButton(R.string.delete, (dlg, btn) -> deleteProxy(proxyUrl))
|
||||||
|
.setNegativeButton(android.R.string.cancel, null)
|
||||||
|
.show();
|
||||||
|
Util.redPositiveButton(dialog);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteProxy(String proxyUrl) {
|
||||||
|
final LinkedList<String> proxies = new LinkedList<>();
|
||||||
|
for (String proxy: DcHelper.get(this, CONFIG_PROXY_URL).split("\n")) {
|
||||||
|
if (!proxy.equals(proxyUrl)) {
|
||||||
|
proxies.add(proxy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (proxies.isEmpty()) {
|
||||||
|
DcHelper.set(this, CONFIG_PROXY_ENABLED, "0");
|
||||||
|
proxySwitch.setChecked(false);
|
||||||
|
}
|
||||||
|
String proxyUrls = String.join("\n", proxies);
|
||||||
|
DcHelper.set(this, CONFIG_PROXY_URL, proxyUrls);
|
||||||
|
restartIO();
|
||||||
|
adapter.changeData(proxyUrls);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showAddProxyDialog() {
|
||||||
|
View view = View.inflate(this, R.layout.single_line_input, null);
|
||||||
|
EditText inputField = view.findViewById(R.id.input_field);
|
||||||
|
inputField.setHint(R.string.proxy_add_url_hint);
|
||||||
|
|
||||||
|
new AlertDialog.Builder(this)
|
||||||
|
.setTitle(R.string.proxy_add)
|
||||||
|
.setMessage(R.string.proxy_add_explain)
|
||||||
|
.setView(view)
|
||||||
|
.setPositiveButton(R.string.proxy_use_proxy, (dialog, whichButton) -> {
|
||||||
|
String newProxy = inputField.getText().toString().trim();
|
||||||
|
DcContext dcContext = DcHelper.getContext(this);
|
||||||
|
final DcLot qrParsed = dcContext.checkQr(newProxy);
|
||||||
|
if (qrParsed.getState() == DcContext.DC_QR_PROXY) {
|
||||||
|
dcContext.setConfigFromQr(newProxy);
|
||||||
|
restartIO();
|
||||||
|
adapter.changeData(DcHelper.get(this, CONFIG_PROXY_URL));
|
||||||
|
} else {
|
||||||
|
Toast.makeText(this, R.string.proxy_invalid, Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
proxySwitch.setChecked(DcHelper.getInt(this, CONFIG_PROXY_ENABLED) == 1);
|
||||||
|
})
|
||||||
|
.setNegativeButton(android.R.string.cancel, (dialog, whichButton) -> {
|
||||||
|
if (proxySwitch.isChecked() && adapter.getCount() == 0) {
|
||||||
|
// user enabled switch without having proxies yet, revert
|
||||||
|
proxySwitch.setChecked(false);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.setCancelable(false)
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void restartIO() {
|
||||||
|
DcContext dcContext = DcHelper.getContext(this);
|
||||||
|
dcContext.stopIo();
|
||||||
|
dcContext.startIo();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleEvent(@NonNull DcEvent event) {
|
||||||
|
if (event.getId() == DcContext.DC_EVENT_CONNECTIVITY_CHANGED) {
|
||||||
|
adapter.refreshConnectivity();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
24
src/main/res/layout/proxy_list_footer.xml
Normal file
24
src/main/res/layout/proxy_list_footer.xml
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingStart="16dp"
|
||||||
|
android:paddingEnd="16dp"
|
||||||
|
android:background="?attr/conversation_list_item_background"
|
||||||
|
>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingTop="10dp"
|
||||||
|
android:paddingBottom="10dp"
|
||||||
|
android:text="@string/proxy_add"
|
||||||
|
android:drawablePadding="5dp"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:ellipsize="marquee"
|
||||||
|
android:fontFamily="sans-serif"
|
||||||
|
android:textSize="16sp"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
13
src/main/res/layout/proxy_list_header.xml
Normal file
13
src/main/res/layout/proxy_list_header.xml
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<TextView
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingStart="16dp"
|
||||||
|
android:paddingEnd="16dp"
|
||||||
|
android:text="@string/proxy_list_header"
|
||||||
|
android:textColor="@color/delta_accent"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:typeface="sans"
|
||||||
|
/>
|
106
src/main/res/layout/proxy_list_item.xml
Normal file
106
src/main/res/layout/proxy_list_item.xml
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:background="?attr/conversation_list_item_background"
|
||||||
|
android:paddingStart="16dp"
|
||||||
|
android:paddingEnd="16dp"
|
||||||
|
android:paddingTop="10dp"
|
||||||
|
android:paddingBottom="10dp"
|
||||||
|
>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/host"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentTop="true"
|
||||||
|
android:layout_alignParentStart="true"
|
||||||
|
android:layout_toStartOf="@id/share"
|
||||||
|
android:drawablePadding="5dp"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:ellipsize="marquee"
|
||||||
|
android:fontFamily="sans-serif"
|
||||||
|
android:textSize="16sp"
|
||||||
|
tools:text="127.0.0.1:1080"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentStart="true"
|
||||||
|
android:layout_below="@+id/host"
|
||||||
|
android:layout_toStartOf="@id/share"
|
||||||
|
android:layout_marginTop="5dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/checkmark"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical|end"
|
||||||
|
android:layout_marginEnd="5dp"
|
||||||
|
android:contentDescription="@null"
|
||||||
|
android:src="@drawable/ic_delivery_status_sent"
|
||||||
|
app:tint="?attr/conversation_list_item_date_color"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/status"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="5dp"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:ellipsize="marquee"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:fontFamily="sans-serif-light"
|
||||||
|
tools:text="@string/connectivity_connected"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/protocol"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:paddingRight="5dp"
|
||||||
|
android:paddingTop="1dp"
|
||||||
|
android:paddingBottom="1dp"
|
||||||
|
android:textAllCaps="true"
|
||||||
|
android:textColor="?attr/conversation_list_item_date_color"
|
||||||
|
android:background="@drawable/archived_indicator_background"
|
||||||
|
style="@style/Signal.Text.Caption"
|
||||||
|
tools:text="socks5"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/share"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:layout_toStartOf="@id/delete"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:layout_marginEnd="5dp"
|
||||||
|
android:contentDescription="@string/menu_share"
|
||||||
|
android:background="@drawable/touch_highlight_background"
|
||||||
|
android:src="@drawable/ic_share_white_24dp"
|
||||||
|
app:tint="?attr/conversation_list_item_date_color"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/delete"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:contentDescription="@string/delete"
|
||||||
|
android:background="@drawable/touch_highlight_background"
|
||||||
|
android:src="@drawable/ic_delete_white_24dp"
|
||||||
|
app:tint="?attr/conversation_list_item_date_color"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
|
@ -1,128 +1,23 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:fillViewport="true"
|
android:orientation="vertical"
|
||||||
tools:context=".ProxySettingsActivity">
|
tools:context=".proxy.ProxySettingsActivity">
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.appcompat.widget.SwitchCompat
|
||||||
android:layout_width="match_parent"
|
android:id="@+id/proxy_switch"
|
||||||
android:layout_height="wrap_content"
|
android:layout_width="match_parent"
|
||||||
android:animateLayoutChanges="true">
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="16dp"
|
||||||
|
android:text="@string/proxy_use_proxy" />
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.Guideline
|
<ListView
|
||||||
android:id="@+id/guideline_root_start_shifted"
|
android:id="@+id/proxy_list"
|
||||||
android:layout_width="wrap_content"
|
android:paddingTop="10dp"
|
||||||
android:layout_height="16dp"
|
android:layout_width="match_parent"
|
||||||
android:orientation="vertical"
|
android:layout_height="wrap_content" />
|
||||||
app:layout_constraintGuide_begin="14dp" />
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.Guideline
|
</LinearLayout>
|
||||||
android:id="@+id/guideline_root_start"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="16dp"
|
|
||||||
android:orientation="vertical"
|
|
||||||
app:layout_constraintGuide_begin="16dp" />
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.Guideline
|
|
||||||
android:id="@+id/guideline_root_end"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical"
|
|
||||||
app:layout_constraintGuide_end="16dp" />
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.SwitchCompat
|
|
||||||
android:id="@+id/proxy_switch"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:paddingTop="16dp"
|
|
||||||
android:paddingBottom="10dp"
|
|
||||||
android:text="@string/proxy_use_proxy"
|
|
||||||
app:layout_constraintEnd_toEndOf="@id/guideline_root_end"
|
|
||||||
app:layout_constraintStart_toStartOf="@id/guideline_root_start"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.Group
|
|
||||||
android:id="@+id/proxy_group"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:visibility="gone"
|
|
||||||
tools:visibility="visible"
|
|
||||||
app:constraint_referenced_ids="proxy_host, proxy_port, proxy_user, proxy_password" />
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
|
||||||
android:id="@+id/proxy_host"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="58dp"
|
|
||||||
app:errorEnabled="true"
|
|
||||||
app:layout_constraintEnd_toEndOf="@id/guideline_root_end"
|
|
||||||
app:layout_constraintStart_toStartOf="@id/guideline_root_start"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/proxy_switch">
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
|
||||||
android:id="@+id/proxy_host_text"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:hint="@string/login_socks5_host"
|
|
||||||
android:inputType="textUri|textNoSuggestions" />
|
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
|
||||||
android:id="@+id/proxy_port"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="58dp"
|
|
||||||
app:errorEnabled="true"
|
|
||||||
app:layout_constraintEnd_toEndOf="@id/guideline_root_end"
|
|
||||||
app:layout_constraintStart_toStartOf="@id/guideline_root_start"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/proxy_host">
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
|
||||||
android:id="@+id/proxy_port_text"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:hint="@string/login_socks5_port"
|
|
||||||
android:inputType="number" />
|
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
|
||||||
android:id="@+id/proxy_user"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:layout_constraintEnd_toEndOf="@id/guideline_root_end"
|
|
||||||
app:layout_constraintStart_toStartOf="@id/guideline_root_start"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/proxy_port">
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
|
||||||
android:id="@+id/proxy_user_text"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:inputType="textNoSuggestions"
|
|
||||||
android:hint="@string/login_socks5_user" />
|
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
|
||||||
android:id="@+id/proxy_password"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:layout_constraintEnd_toEndOf="@id/guideline_root_end"
|
|
||||||
app:layout_constraintStart_toStartOf="@id/guideline_root_start"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/proxy_user"
|
|
||||||
app:passwordToggleEnabled="true">
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
|
||||||
android:id="@+id/proxy_password_text"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:hint="@string/login_socks5_password"
|
|
||||||
android:inputType="textPassword" />
|
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
|
|
||||||
</ScrollView>
|
|
||||||
|
|
|
@ -608,13 +608,22 @@
|
||||||
<!-- the word "Proxy" might be left untranslated unless the destination language has a well-known term for a "Proxy Server", acting intermediary between the app and the chatmail or email server -->
|
<!-- the word "Proxy" might be left untranslated unless the destination language has a well-known term for a "Proxy Server", acting intermediary between the app and the chatmail or email server -->
|
||||||
<string name="proxy_settings">Proxy</string>
|
<string name="proxy_settings">Proxy</string>
|
||||||
<string name="proxy_use_proxy">Use Proxy</string>
|
<string name="proxy_use_proxy">Use Proxy</string>
|
||||||
<!-- the word "SOCKS5" here and in the following strings should not be translated in most cases -->
|
<string name="proxy_add">Add Proxy</string>
|
||||||
|
<string name="proxy_add_explain">Supported proxy types: HTTP(S), SOCKS5 and Shadowsocks.</string>
|
||||||
|
<string name="proxy_add_url_hint">Enter proxy URL here</string>
|
||||||
|
<string name="proxy_invalid">Invalid or unsupported proxy URL</string>
|
||||||
|
<string name="proxy_list_header">Connections</string>
|
||||||
|
<string name="proxy_delete">Delete Proxy</string>
|
||||||
|
<string name="proxy_delete_explain">Are you sure you want to delete \"%1$s\"?</string>
|
||||||
|
|
||||||
|
<!-- deprecated -->
|
||||||
<string name="login_socks5">SOCKS5</string>
|
<string name="login_socks5">SOCKS5</string>
|
||||||
<string name="login_socks5_use_socks5">Use SOCKS5</string>
|
<string name="login_socks5_use_socks5">Use SOCKS5</string>
|
||||||
<string name="login_socks5_host">SOCKS5 Host</string>
|
<string name="login_socks5_host">SOCKS5 Host</string>
|
||||||
<string name="login_socks5_port">SOCKS5 Port</string>
|
<string name="login_socks5_port">SOCKS5 Port</string>
|
||||||
<string name="login_socks5_user">SOCKS5 User</string>
|
<string name="login_socks5_user">SOCKS5 User</string>
|
||||||
<string name="login_socks5_password">SOCKS5 Password</string>
|
<string name="login_socks5_password">SOCKS5 Password</string>
|
||||||
|
|
||||||
<string name="login_info_oauth2_title">Continue with simplified setup?</string>
|
<string name="login_info_oauth2_title">Continue with simplified setup?</string>
|
||||||
<string name="login_info_oauth2_text">The entered e-mail address supports a simplified setup (OAuth 2.0).\n\nIn the next step, please allow Delta Chat to act as your Chat over E-mail app.\n\nDelta Chat does not collect user data, everything stays on your device.</string>
|
<string name="login_info_oauth2_text">The entered e-mail address supports a simplified setup (OAuth 2.0).\n\nIn the next step, please allow Delta Chat to act as your Chat over E-mail app.\n\nDelta Chat does not collect user data, everything stays on your device.</string>
|
||||||
<string name="login_certificate_checks">Certificate Checks</string>
|
<string name="login_certificate_checks">Certificate Checks</string>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue