diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/contact/ContactManager.java b/bramble-api/src/main/java/org/briarproject/bramble/api/contact/ContactManager.java index eca1e0720..a11226bc6 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/contact/ContactManager.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/contact/ContactManager.java @@ -1,5 +1,6 @@ package org.briarproject.bramble.api.contact; +import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.Transaction; @@ -60,16 +61,16 @@ public interface ContactManager { /** * Returns the static link that needs to be sent to the contact to be added. */ - String getRemoteContactLink() throws DbException; + String getHandshakeLink() throws DbException; /** * Requests a new contact to be added via the given {@code link}. * * @param link The link received from the contact we want to add. * @param alias The alias the user has given this contact. - * @return A PendingContact representing the contact to be added. */ - void addRemoteContactRequest(String link, String alias); + void addPendingContact(String link, String alias) + throws DbException, FormatException; /** * Returns a list of {@link PendingContact}s. @@ -81,7 +82,7 @@ public interface ContactManager { * {@link PendingContactState FAILED}. * @param commitAction an action to run on the main thread after removing. */ - void removePendingContact(PendingContact pendingContact, + void removePendingContact(PendingContactId pendingContact, Runnable commitAction) throws DbException; /** diff --git a/bramble-core/src/main/java/org/briarproject/bramble/contact/ContactManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/contact/ContactManagerImpl.java index dd0247160..5f4912d99 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/contact/ContactManagerImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/contact/ContactManagerImpl.java @@ -116,7 +116,7 @@ class ContactManagerImpl implements ContactManager { } @Override - public String getRemoteContactLink() { + public String getHandshakeLink() { // TODO replace with real implementation try { Thread.sleep(1500); @@ -139,27 +139,23 @@ class ContactManagerImpl implements ContactManager { } @Override - public void addRemoteContactRequest(String link, String alias) { + public void addPendingContact(String link, String alias) + throws DbException { // TODO replace with real implementation + try { + Thread.sleep(1500); + } catch (InterruptedException ignored) { + } PendingContactId id = new PendingContactId( link.substring(0, PendingContactId.LENGTH).getBytes()); PendingContact pendingContact = new PendingContact(id, new byte[MAX_PUBLIC_KEY_LENGTH], alias, WAITING_FOR_CONNECTION, currentTimeMillis()); - dbExecutor.execute(() -> { - try { - Thread.sleep(1500); - } catch (InterruptedException ignored) { - } - try { - getLogger("TMP").warning("WAITING_FOR_CONNECTION"); - pendingContacts.add(pendingContact); - Event e = new PendingContactStateChangedEvent(id, - WAITING_FOR_CONNECTION); - db.transaction(true, txn -> txn.attach(e)); - } catch (DbException ignored) { - } - }); + getLogger("TMP").warning("WAITING_FOR_CONNECTION"); + pendingContacts.add(pendingContact); + Event event = new PendingContactStateChangedEvent(id, + WAITING_FOR_CONNECTION); + db.transaction(true, txn -> txn.attach(event)); scheduler.schedule(() -> dbExecutor.execute(() -> { getLogger("TMP").warning("CONNECTED"); @@ -222,10 +218,15 @@ class ContactManagerImpl implements ContactManager { } @Override - public void removePendingContact(PendingContact pendingContact, + public void removePendingContact(PendingContactId id, Runnable commitAction) throws DbException { // TODO replace with real implementation - pendingContacts.remove(pendingContact); + for (PendingContact pc : pendingContacts) { + if (pc.getId().equals(id)) { + pendingContacts.remove(pc); + break; + } + } try { Thread.sleep(250); } catch (InterruptedException ignored) { diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/AddContactActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/AddContactActivity.java index c732660a3..1a6d55f75 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/AddContactActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/AddContactActivity.java @@ -63,7 +63,7 @@ public class AddContactActivity extends BriarActivity implements String text = i.getStringExtra(EXTRA_TEXT); if (text != null) { if (viewModel.isValidRemoteContactLink(text)) { - viewModel.setRemoteContactLink(text); + viewModel.setRemoteHandshakeLink(text); } else { Toast.makeText(this, R.string.invalid_link, LENGTH_LONG) .show(); @@ -72,7 +72,7 @@ public class AddContactActivity extends BriarActivity implements String uri = i.getDataString(); if (uri != null) { if (viewModel.isValidRemoteContactLink(uri)) { - viewModel.setRemoteContactLink(uri); + viewModel.setRemoteHandshakeLink(uri); } else { Toast.makeText(this, R.string.invalid_link, LENGTH_LONG) .show(); 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 45d1ae2d9..bc58fabfc 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 @@ -7,6 +7,7 @@ import android.arch.lifecycle.MutableLiveData; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.contact.ContactManager; import org.briarproject.bramble.api.db.DatabaseExecutor; import org.briarproject.bramble.api.db.DbException; @@ -32,11 +33,14 @@ public class AddContactViewModel extends AndroidViewModel { @DatabaseExecutor private final Executor dbExecutor; - private final MutableLiveData ourLink = new MutableLiveData<>(); + private final MutableLiveData handshakeLink = + new MutableLiveData<>(); private final MutableLiveData remoteLinkEntered = new MutableLiveData<>(); + private final MutableLiveData addContactResult = + new MutableLiveData<>(); @Nullable - private String remoteContactLink; + private String remoteHandshakeLink; @Inject public AddContactViewModel(@NonNull Application application, @@ -45,13 +49,13 @@ public class AddContactViewModel extends AndroidViewModel { super(application); this.contactManager = contactManager; this.dbExecutor = dbExecutor; - loadOurLink(); + loadHandshakeLink(); } - private void loadOurLink() { + private void loadHandshakeLink() { dbExecutor.execute(() -> { try { - ourLink.postValue(contactManager.getRemoteContactLink()); + handshakeLink.postValue(contactManager.getHandshakeLink()); } catch (DbException e) { logException(LOG, WARNING, e); // the UI should stay disable in this case, @@ -60,12 +64,12 @@ public class AddContactViewModel extends AndroidViewModel { }); } - LiveData getOurLink() { - return ourLink; + LiveData getHandshakeLink() { + return handshakeLink; } - void setRemoteContactLink(String link) { - remoteContactLink = link; + void setRemoteHandshakeLink(String link) { + remoteHandshakeLink = link; } boolean isValidRemoteContactLink(@Nullable CharSequence link) { @@ -77,14 +81,26 @@ public class AddContactViewModel extends AndroidViewModel { } void onRemoteLinkEntered() { - if (remoteContactLink == null) throw new IllegalStateException(); + if (remoteHandshakeLink == null) throw new IllegalStateException(); remoteLinkEntered.setValue(true); remoteLinkEntered.postValue(false); // reset, so we can navigate back } void addContact(String nickname) { - if (remoteContactLink == null) throw new IllegalStateException(); - contactManager.addRemoteContactRequest(remoteContactLink, nickname); + if (remoteHandshakeLink == null) throw new IllegalStateException(); + dbExecutor.execute(() -> { + try { + contactManager.addPendingContact(remoteHandshakeLink, nickname); + addContactResult.postValue(true); + } catch (DbException | FormatException e) { + logException(LOG, WARNING, e); + addContactResult.postValue(false); + } + }); + } + + public LiveData getAddContactResult() { + return addContactResult; } } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/LinkExchangeFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/LinkExchangeFragment.java index 82e971d4d..bca1876e4 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/LinkExchangeFragment.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/LinkExchangeFragment.java @@ -83,12 +83,13 @@ public class LinkExchangeFragment extends BaseFragment { linkInput.setText(clipData.getItemAt(0).getText()); }); - observeOnce(viewModel.getOurLink(), this, this::onOwnLinkLoaded); + observeOnce(viewModel.getHandshakeLink(), this, + this::onHandshakeLinkLoaded); return v; } - private void onOwnLinkLoaded(String link) { + private void onHandshakeLinkLoaded(String link) { View v = requireNonNull(getView()); TextView linkView = v.findViewById(R.id.linkView); @@ -118,10 +119,10 @@ public class LinkExchangeFragment extends BaseFragment { } /** - * Requires {@link AddContactViewModel#getOurLink()} to be loaded. + * Requires {@link AddContactViewModel#getHandshakeLink()} to be loaded. */ @Nullable - private String getEnteredLinkOrNull() { + private String getRemoteHandshakeLinkOrNull() { CharSequence link = linkInput.getText(); if (link == null || link.length() == 0) { linkInputLayout.setError(getString(R.string.missing_link)); @@ -135,7 +136,7 @@ public class LinkExchangeFragment extends BaseFragment { // Check also if this is our own link. This was loaded already, // because it enables the Continue button which is the only caller. if (("briar://" + linkWithoutSchema) - .equals(viewModel.getOurLink().getValue())) { + .equals(viewModel.getHandshakeLink().getValue())) { linkInputLayout.setError(getString(R.string.own_link_error)); linkInput.requestFocus(); return null; @@ -149,10 +150,10 @@ public class LinkExchangeFragment extends BaseFragment { } private void onContinueButtonClicked() { - String link = getEnteredLinkOrNull(); + String link = getRemoteHandshakeLinkOrNull(); if (link == null) return; // invalid link - viewModel.setRemoteContactLink(link); + viewModel.setRemoteHandshakeLink(link); viewModel.onRemoteLinkEntered(); } 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 79d94bde1..fc1ad3469 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 @@ -11,6 +11,8 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; +import android.widget.ProgressBar; +import android.widget.Toast; import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; @@ -21,6 +23,9 @@ import org.briarproject.briar.android.fragment.BaseFragment; import javax.annotation.Nullable; import javax.inject.Inject; +import static android.view.View.INVISIBLE; +import static android.view.View.VISIBLE; +import static android.widget.Toast.LENGTH_LONG; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH; import static org.briarproject.bramble.util.StringUtils.utf8IsTooLong; @@ -37,6 +42,8 @@ public class NicknameFragment extends BaseFragment { private TextInputLayout contactNameLayout; private TextInputEditText contactNameInput; + private Button addButton; + private ProgressBar progressBar; @Override public String getUniqueTag() { @@ -61,12 +68,14 @@ public class NicknameFragment extends BaseFragment { viewModel = ViewModelProviders.of(getActivity(), viewModelFactory) .get(AddContactViewModel.class); - Button addButton = v.findViewById(R.id.addButton); - addButton.setOnClickListener(view -> onAddButtonClicked()); - contactNameLayout = v.findViewById(R.id.contactNameLayout); contactNameInput = v.findViewById(R.id.contactNameInput); + addButton = v.findViewById(R.id.addButton); + addButton.setOnClickListener(view -> onAddButtonClicked()); + + progressBar = v.findViewById(R.id.progressBar); + return v; } @@ -91,12 +100,22 @@ public class NicknameFragment extends BaseFragment { String name = getNicknameOrNull(); if (name == null) return; // invalid nickname - viewModel.addContact(name); + addButton.setVisibility(INVISIBLE); + progressBar.setVisibility(VISIBLE); - Intent intent = - new Intent(getActivity(), PendingContactListActivity.class); - startActivity(intent); - finish(); + viewModel.getAddContactResult().observe(this, success -> { + if (success == null) return; + if (success) { + Intent intent = new Intent(getActivity(), + PendingContactListActivity.class); + startActivity(intent); + } else { + Toast.makeText(getContext(), R.string.adding_contact_error, + LENGTH_LONG).show(); + } + finish(); + }); + viewModel.addContact(name); } } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/PendingContactListActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/PendingContactListActivity.java index 3e329e2e1..b716222ee 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/PendingContactListActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/PendingContactListActivity.java @@ -86,7 +86,7 @@ public class PendingContactListActivity extends BriarActivity @Override public void onFailedPendingContactRemoved(PendingContact pendingContact) { - viewModel.removePendingContact(pendingContact, + viewModel.removePendingContact(pendingContact.getId(), () -> adapter.remove(pendingContact)); } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/PendingContactListViewModel.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/PendingContactListViewModel.java index 65efb2263..c97e0538b 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/PendingContactListViewModel.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/PendingContactListViewModel.java @@ -7,6 +7,7 @@ import android.arch.lifecycle.MutableLiveData; import org.briarproject.bramble.api.contact.ContactManager; import org.briarproject.bramble.api.contact.PendingContact; +import org.briarproject.bramble.api.contact.PendingContactId; import org.briarproject.bramble.api.contact.event.ContactAddedRemotelyEvent; import org.briarproject.bramble.api.contact.event.PendingContactStateChangedEvent; import org.briarproject.bramble.api.db.DatabaseExecutor; @@ -81,12 +82,11 @@ public class PendingContactListViewModel extends AndroidViewModel return pendingContacts; } - void removePendingContact(PendingContact pendingContact, - Runnable commitAction) { + void removePendingContact(PendingContactId id, Runnable commitAction) { dbExecutor.execute(() -> { try { contactManager - .removePendingContact(pendingContact, commitAction); + .removePendingContact(id, commitAction); } catch (DbException e) { logException(LOG, WARNING, e); } diff --git a/briar-android/src/main/res/layout/fragment_nickname.xml b/briar-android/src/main/res/layout/fragment_nickname.xml index e4e655f9b..5f681869d 100644 --- a/briar-android/src/main/res/layout/fragment_nickname.xml +++ b/briar-android/src/main/res/layout/fragment_nickname.xml @@ -145,6 +145,19 @@ app:layout_constraintTop_toBottomOf="@+id/contactNameLayout" app:layout_constraintVertical_bias="1.0"/> + + \ No newline at end of file diff --git a/briar-android/src/main/res/values/strings.xml b/briar-android/src/main/res/values/strings.xml index c14785314..83ffb5e82 100644 --- a/briar-android/src/main/res/values/strings.xml +++ b/briar-android/src/main/res/values/strings.xml @@ -188,6 +188,7 @@ Give this link to the contact you want to add Briar link Link copied + There was an error adding the contact. There are pending contact requests Pending Contact Requests No pending contacts