diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml
index 3eca0084a..f044dd848 100644
--- a/src/main/AndroidManifest.xml
+++ b/src/main/AndroidManifest.xml
@@ -241,7 +241,7 @@
android:exported="true">
-
diff --git a/src/main/java/org/thoughtcrime/securesms/TransportListActivity.java b/src/main/java/org/thoughtcrime/securesms/TransportListActivity.java
deleted file mode 100644
index e69de29bb..000000000
diff --git a/src/main/java/org/thoughtcrime/securesms/preferences/AdvancedPreferenceFragment.java b/src/main/java/org/thoughtcrime/securesms/preferences/AdvancedPreferenceFragment.java
index 1432bc852..5387114b0 100644
--- a/src/main/java/org/thoughtcrime/securesms/preferences/AdvancedPreferenceFragment.java
+++ b/src/main/java/org/thoughtcrime/securesms/preferences/AdvancedPreferenceFragment.java
@@ -7,9 +7,7 @@ import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_MVBOX_MOVE;
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_ONLY_FETCH_MVBOX;
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_SHOW_EMAILS;
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_WEBXDC_REALTIME_ENABLED;
-import static org.thoughtcrime.securesms.connect.DcHelper.getRpc;
-import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -17,7 +15,6 @@ import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
-import android.webkit.WebView;
import android.widget.EditText;
import android.widget.Toast;
@@ -29,12 +26,10 @@ import androidx.preference.ListPreference;
import androidx.preference.Preference;
import org.thoughtcrime.securesms.ApplicationPreferencesActivity;
-import org.thoughtcrime.securesms.ConversationActivity;
import org.thoughtcrime.securesms.LogViewActivity;
import org.thoughtcrime.securesms.R;
-import org.thoughtcrime.securesms.EditTransportActivity;
+import org.thoughtcrime.securesms.relay.RelayListActivity;
import org.thoughtcrime.securesms.connect.DcEventCenter;
-import org.thoughtcrime.securesms.connect.DcHelper;
import org.thoughtcrime.securesms.proxy.ProxySettingsActivity;
import org.thoughtcrime.securesms.util.Prefs;
import org.thoughtcrime.securesms.util.ScreenLockUtil;
@@ -48,8 +43,6 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.util.Objects;
-import chat.delta.rpc.RpcException;
-
public class AdvancedPreferenceFragment extends ListSummaryPreferenceFragment
implements DcEventCenter.DcEventDelegate
@@ -207,12 +200,12 @@ public class AdvancedPreferenceFragment extends ListSummaryPreferenceFragment
});
}
- Preference passwordAndAccount = this.findPreference("password_account_settings_button");
- if (passwordAndAccount != null) {
- passwordAndAccount.setOnPreferenceClickListener(((preference) -> {
- boolean result = ScreenLockUtil.applyScreenLock(requireActivity(), getString(R.string.edit_transport), getString(R.string.enter_system_secret_to_continue), REQUEST_CODE_CONFIRM_CREDENTIALS_ACCOUNT);
+ Preference relayListBtn = this.findPreference("pref_relay_list_button");
+ if (relayListBtn != null) {
+ relayListBtn.setOnPreferenceClickListener(((preference) -> {
+ boolean result = ScreenLockUtil.applyScreenLock(requireActivity(), getString(R.string.transports), getString(R.string.enter_system_secret_to_continue), REQUEST_CODE_CONFIRM_CREDENTIALS_ACCOUNT);
if (!result) {
- openRegistrationActivity();
+ openRelayListActivity();
}
return true;
}));
@@ -247,7 +240,7 @@ public class AdvancedPreferenceFragment extends ListSummaryPreferenceFragment
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK && requestCode == REQUEST_CODE_CONFIRM_CREDENTIALS_ACCOUNT) {
- openRegistrationActivity();
+ openRelayListActivity();
}
}
@@ -324,8 +317,8 @@ public class AdvancedPreferenceFragment extends ListSummaryPreferenceFragment
}
}
- private void openRegistrationActivity() {
- Intent intent = new Intent(requireActivity(), EditTransportActivity.class);
+ private void openRelayListActivity() {
+ Intent intent = new Intent(requireActivity(), RelayListActivity.class);
startActivity(intent);
}
diff --git a/src/main/java/org/thoughtcrime/securesms/relay/RelayListActivity.java b/src/main/java/org/thoughtcrime/securesms/relay/RelayListActivity.java
new file mode 100644
index 000000000..1a2f430cc
--- /dev/null
+++ b/src/main/java/org/thoughtcrime/securesms/relay/RelayListActivity.java
@@ -0,0 +1,112 @@
+package org.thoughtcrime.securesms.relay;
+
+import android.os.Bundle;
+import android.util.Log;
+import android.view.MenuItem;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.ActionBar;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import org.thoughtcrime.securesms.BaseActionBarActivity;
+import org.thoughtcrime.securesms.R;
+import org.thoughtcrime.securesms.connect.DcHelper;
+import org.thoughtcrime.securesms.util.Util;
+import org.thoughtcrime.securesms.util.ViewUtil;
+
+import java.util.List;
+
+import chat.delta.rpc.Rpc;
+import chat.delta.rpc.RpcException;
+import chat.delta.rpc.types.EnteredLoginParam;
+
+public class RelayListActivity extends BaseActionBarActivity
+ implements RelayListAdapter.OnRelayClickListener {
+
+ private static final String TAG = RelayListActivity.class.getSimpleName();
+
+ private RelayListAdapter adapter;
+ private Rpc rpc;
+ private int accId;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_relay_list);
+
+ rpc = DcHelper.getRpc(this);
+ accId = DcHelper.getContext(this).getAccountId();
+
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setTitle(R.string.transports);
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ }
+
+ RecyclerView recyclerView = findViewById(R.id.relay_list);
+
+ // add padding to avoid content hidden behind system bars
+ ViewUtil.applyWindowInsets(recyclerView);
+
+ LinearLayoutManager layoutManager = new LinearLayoutManager(this);
+ // Add the default divider (uses the theme’s `android.R.attr.listDivider`)
+ DividerItemDecoration divider = new DividerItemDecoration(
+ recyclerView.getContext(),
+ layoutManager.getOrientation());
+ recyclerView.addItemDecoration(divider);
+ recyclerView.setLayoutManager(layoutManager);
+
+ adapter = new RelayListAdapter(this);
+ recyclerView.setAdapter(adapter);
+
+ loadRelays();
+ }
+
+ }
+
+ private void loadRelays() {
+ Util.runOnAnyBackgroundThread(() -> {
+ String mainRelayAddr = "";
+ try {
+ mainRelayAddr = rpc.getConfig(accId, DcHelper.CONFIG_CONFIGURED_ADDRESS);
+ } catch (RpcException e) {
+ Log.e(TAG, "RPC.getConfig() failed", e);
+ }
+ String finalMainRelayAddr = mainRelayAddr;
+
+ try {
+ List relays = rpc.listTransports(accId);
+
+ Util.runOnMain(() -> adapter.setRelays(relays, finalMainRelayAddr));
+ } catch (RpcException e) {
+ Log.e(TAG, "RPC.listTransports() failed", e);
+ Util.runOnMain(() -> adapter.setRelays(null, finalMainRelayAddr));
+ }
+ });
+ }
+
+ @Override
+ public void onRelayClick(EnteredLoginParam relay) {
+ if (relay.addr != null && !relay.addr.equals(adapter.getMainRelay())) {
+ Util.runOnAnyBackgroundThread(() -> {
+ try {
+ rpc.setConfig(accId, DcHelper.CONFIG_CONFIGURED_ADDRESS, relay.addr);
+ } catch (RpcException e) {
+ Log.e(TAG, "RPC.setConfig() failed", e);
+ }
+
+ loadRelays();
+ });
+ }
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(@NonNull MenuItem item) {
+ if (item.getItemId() == android.R.id.home) {
+ finish();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+}
diff --git a/src/main/java/org/thoughtcrime/securesms/relay/RelayListAdapter.java b/src/main/java/org/thoughtcrime/securesms/relay/RelayListAdapter.java
new file mode 100644
index 000000000..191847e50
--- /dev/null
+++ b/src/main/java/org/thoughtcrime/securesms/relay/RelayListAdapter.java
@@ -0,0 +1,84 @@
+package org.thoughtcrime.securesms.relay;
+
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
+import org.thoughtcrime.securesms.R;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import chat.delta.rpc.types.EnteredLoginParam;
+
+public class RelayListAdapter extends RecyclerView.Adapter {
+
+ private List relays = new ArrayList<>();
+ private final OnRelayClickListener listener;
+ private String mainRelayAddr;
+
+ public interface OnRelayClickListener {
+ void onRelayClick(EnteredLoginParam relay);
+ }
+
+ public RelayListAdapter(OnRelayClickListener listener) {
+ this.listener = listener;
+ }
+
+ public String getMainRelay() {
+ return mainRelayAddr;
+ }
+
+ public void setRelays(List relays, String mainRelayAddr) {
+ this.relays = relays != null ? relays : new ArrayList<>();
+ this.mainRelayAddr = mainRelayAddr;
+ notifyDataSetChanged();
+ }
+
+ @NonNull
+ @Override
+ public RelayViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ View view = LayoutInflater.from(parent.getContext())
+ .inflate(R.layout.relay_list_item, parent, false);
+ return new RelayViewHolder(view);
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull RelayViewHolder holder, int position) {
+ EnteredLoginParam relay = relays.get(position);
+ boolean isMain = relay.addr != null && relay.addr.equals(mainRelayAddr);
+ holder.bind(relay, isMain, listener);
+ }
+
+ @Override
+ public int getItemCount() {
+ return relays.size();
+ }
+
+ public static class RelayViewHolder extends RecyclerView.ViewHolder {
+ private final TextView titleText;
+ private final ImageView mainIndicator;
+
+ public RelayViewHolder(@NonNull View itemView) {
+ super(itemView);
+ titleText = itemView.findViewById(R.id.title);
+ mainIndicator = itemView.findViewById(R.id.main_indicator);
+ }
+
+ public void bind(EnteredLoginParam relay, boolean isMain, OnRelayClickListener listener) {
+ titleText.setText(relay.addr);
+ mainIndicator.setVisibility(isMain ? View.VISIBLE : View.GONE);
+
+ itemView.setOnClickListener(v -> {
+ if (listener != null) {
+ listener.onRelayClick(relay);
+ }
+ });
+ }
+ }
+}
diff --git a/src/main/res/layout/activity_relay_list.xml b/src/main/res/layout/activity_relay_list.xml
new file mode 100644
index 000000000..af7e550ca
--- /dev/null
+++ b/src/main/res/layout/activity_relay_list.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
diff --git a/src/main/res/layout/relay_list_item.xml b/src/main/res/layout/relay_list_item.xml
new file mode 100644
index 000000000..329fb7d14
--- /dev/null
+++ b/src/main/res/layout/relay_list_item.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index 6065dba54..368400a56 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -681,6 +681,7 @@
You are using a proxy. If you\'re having trouble connecting, try a different proxy.
Transports
+ Main transport
Add Transport
Remove Transport
Edit Transport
diff --git a/src/main/res/xml/preferences_advanced.xml b/src/main/res/xml/preferences_advanced.xml
index 9cf402105..0b8d71809 100644
--- a/src/main/res/xml/preferences_advanced.xml
+++ b/src/main/res/xml/preferences_advanced.xml
@@ -7,8 +7,8 @@
-
+