diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/AddContactViewModel.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/AddContactViewModel.java
index 718cdc83d..901f5773d 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/AddContactViewModel.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/AddContactViewModel.java
@@ -9,6 +9,7 @@ import android.support.annotation.Nullable;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.UnsupportedVersionException;
import org.briarproject.bramble.api.contact.ContactManager;
+import org.briarproject.bramble.api.contact.PendingContact;
import org.briarproject.bramble.api.db.DatabaseExecutor;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@@ -25,6 +26,7 @@ import javax.inject.Inject;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.api.contact.HandshakeLinkConstants.LINK_REGEX;
+import static org.briarproject.bramble.api.contact.PendingContactState.FAILED;
import static org.briarproject.bramble.util.LogUtils.logException;
@NotNullByDefault
@@ -118,4 +120,18 @@ public class AddContactViewModel extends AndroidViewModel {
return addContactResult;
}
+ public void updatePendingContact(String name, PendingContact p) {
+ dbExecutor.execute(() -> {
+ if (contactManager.getPendingContactState(p.getId()) == FAILED) {
+ try {
+ contactManager.removePendingContact(p.getId());
+ } catch (DbException e) {
+ logException(LOG, WARNING, e);
+ addContactResult.postValue(new LiveResult<>(e));
+ }
+ addContact(name);
+ }
+ });
+ }
+
}
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/NicknameFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/NicknameFragment.java
index e1cfd7dba..0e561718d 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/NicknameFragment.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/NicknameFragment.java
@@ -2,10 +2,15 @@ package org.briarproject.briar.android.contact.add.remote;
import android.arch.lifecycle.ViewModelProvider;
import android.arch.lifecycle.ViewModelProviders;
+import android.content.Context;
+import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
+import android.graphics.drawable.Drawable;
import android.os.Bundle;
+import android.support.annotation.StringRes;
import android.support.design.widget.TextInputEditText;
import android.support.design.widget.TextInputLayout;
+import android.support.v7.app.AlertDialog.Builder;
import android.text.Editable;
import android.view.LayoutInflater;
import android.view.View;
@@ -15,6 +20,10 @@ import android.widget.ProgressBar;
import android.widget.Toast;
import org.briarproject.bramble.api.UnsupportedVersionException;
+import org.briarproject.bramble.api.contact.PendingContact;
+import org.briarproject.bramble.api.db.ContactExistsException;
+import org.briarproject.bramble.api.db.PendingContactExistsException;
+import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.briar.R;
@@ -24,9 +33,13 @@ import org.briarproject.briar.android.fragment.BaseFragment;
import javax.annotation.Nullable;
import javax.inject.Inject;
+import static android.support.v4.content.ContextCompat.getColor;
+import static android.support.v4.content.ContextCompat.getDrawable;
+import static android.support.v4.graphics.drawable.DrawableCompat.setTint;
import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE;
import static android.widget.Toast.LENGTH_LONG;
+import static java.util.Objects.requireNonNull;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.util.StringUtils.utf8IsTooLong;
@@ -107,23 +120,93 @@ public class NicknameFragment extends BaseFragment {
viewModel.getAddContactResult().observe(this, result -> {
if (result == null) return;
- if (result.hasError()) {
- int stringRes;
- if (result
- .getException() instanceof UnsupportedVersionException) {
- stringRes = R.string.unsupported_link;
- } else {
- stringRes = R.string.adding_contact_error;
- }
- Toast.makeText(getContext(), stringRes, LENGTH_LONG).show();
- } else {
- Intent intent = new Intent(getActivity(),
- PendingContactListActivity.class);
- startActivity(intent);
- }
- finish();
+ if (result.hasError()) handleException(name, result.getException());
+ else showPendingContactListActivity();
});
viewModel.addContact(name);
}
+ private void showPendingContactListActivity() {
+ Intent intent = new Intent(getActivity(),
+ PendingContactListActivity.class);
+ startActivity(intent);
+ finish();
+ }
+
+ private void handleException(String name, @Nullable Exception e) {
+ if (e instanceof ContactExistsException) {
+ ContactExistsException ce = (ContactExistsException) e;
+ handleExistingContact(name, ce.getRemoteAuthor());
+ } else if (e instanceof PendingContactExistsException) {
+ PendingContactExistsException pe =
+ (PendingContactExistsException) e;
+ handleExistingPendingContact(name, pe.getPendingContact());
+ } else if (e instanceof UnsupportedVersionException) {
+ int stringRes = R.string.unsupported_link;
+ Toast.makeText(getContext(), stringRes, LENGTH_LONG).show();
+ finish();
+ } else {
+ int stringRes = R.string.adding_contact_error;
+ Toast.makeText(getContext(), stringRes, LENGTH_LONG).show();
+ finish();
+ }
+ }
+
+ private void handleExistingContact(String name, Author existing) {
+ OnClickListener listener = (d, w) -> {
+ d.dismiss();
+ String str = getString(R.string.contact_already_exists, name);
+ Toast.makeText(getContext(), str, LENGTH_LONG).show();
+ finish();
+ };
+ showSameLinkDialog(existing.getName(), name,
+ R.string.duplicate_link_dialog_text_1_contact, listener);
+ }
+
+ private void handleExistingPendingContact(String name, PendingContact p) {
+ OnClickListener listener = (d, w) -> {
+ viewModel.updatePendingContact(name, p);
+ Toast.makeText(getContext(), R.string.pending_contact_updated_toast,
+ LENGTH_LONG).show();
+ d.dismiss();
+ showPendingContactListActivity();
+ };
+ showSameLinkDialog(p.getAlias(), name,
+ R.string.duplicate_link_dialog_text_1, listener);
+ }
+
+ private void showSameLinkDialog(String name1, String name2,
+ @StringRes int existsRes, OnClickListener samePersonListener) {
+ Context ctx = requireContext();
+ Builder b = new Builder(ctx, R.style.BriarDialogTheme_Neutral);
+ b.setTitle(getString(R.string.duplicate_link_dialog_title));
+ String msg = getString(existsRes, name1) + "\n\n" +
+ getString(R.string.duplicate_link_dialog_text_2, name2, name1);
+ b.setMessage(msg);
+ b.setPositiveButton(R.string.same_person_button, samePersonListener);
+ b.setNegativeButton(R.string.different_person_button, (d, w) -> {
+ d.dismiss();
+ showWarningDialog(name1, name2);
+ });
+ b.setCancelable(false);
+ b.show();
+ }
+
+ private void showWarningDialog(String name1, String name2) {
+ Context ctx = requireContext();
+ Builder b = new Builder(ctx, R.style.BriarDialogTheme);
+ Drawable icon = getDrawable(ctx, R.drawable.alerts_and_states_error);
+ setTint(requireNonNull(icon), getColor(ctx, R.color.color_primary));
+ b.setIcon(icon);
+ b.setTitle(getString(R.string.duplicate_link_dialog_title));
+ b.setMessage(
+ getString(R.string.duplicate_link_dialog_text_3, name1, name2));
+ b.setPositiveButton(R.string.ok, (d, w) -> {
+ d.dismiss();
+ finish();
+ });
+ b.setCancelable(false);
+ b.show();
+ }
+
}
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/ContactExchangeActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/ContactExchangeActivity.java
index 7372ae2ae..56ef169b0 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/ContactExchangeActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/ContactExchangeActivity.java
@@ -62,8 +62,7 @@ public class ContactExchangeActivity extends KeyAgreementActivity {
@UiThread
private void contactExchangeSucceeded(Author remoteAuthor) {
String contactName = remoteAuthor.getName();
- String format = getString(R.string.contact_added_toast);
- String text = String.format(format, contactName);
+ String text = getString(R.string.contact_added_toast, contactName);
Toast.makeText(this, text, LENGTH_LONG).show();
supportFinishAfterTransition();
}
diff --git a/briar-android/src/main/res/values-zh-rCN/strings.xml b/briar-android/src/main/res/values-zh-rCN/strings.xml
index fb3e7d700..e171fa797 100644
--- a/briar-android/src/main/res/values-zh-rCN/strings.xml
+++ b/briar-android/src/main/res/values-zh-rCN/strings.xml
@@ -199,7 +199,7 @@
添加此联系人比通常花费了更多时间。\n\n请检查您的联系人是否收到您的链接并已添加您:
无网络连接
重复的链接
- 您已经有此链接的待处理联系人:
+ 您已经有此链接的待处理联系人:%s
%s 和 %s 是同一个人吗?
Are %s and %s the same person?