From f4c7736674748bb9830a0ef7e7b4d375b24189eb Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Tue, 25 Sep 2018 19:31:27 -0300 Subject: [PATCH] Actually add fake contact ~1 minute after entering link --- .../contact/ContactLinkInputActivity.java | 55 ++++++++- .../android/contact/ContactListFragment.java | 33 +++++- .../contact/PendingRequestsActivity.java | 73 +++++++++++- .../contact/PendingRequestsAdapter.java | 26 ++-- .../android/contact/PendingRequestsItem.java | 27 ----- .../contact/PendingRequestsViewHolder.java | 9 +- .../res/layout/list_item_pending_contact.xml | 49 ++++++-- briar-android/src/main/res/values/strings.xml | 1 + .../briar/api/messaging/MessagingManager.java | 22 ++++ .../briar/messaging/MessagingManagerImpl.java | 111 +++++++++++++++++- 10 files changed, 358 insertions(+), 48 deletions(-) delete mode 100644 briar-android/src/main/java/org/briarproject/briar/android/contact/PendingRequestsItem.java diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactLinkInputActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactLinkInputActivity.java index 72d9932b7..7533f7cd6 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactLinkInputActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactLinkInputActivity.java @@ -1,5 +1,7 @@ package org.briarproject.briar.android.contact; +import android.app.AlarmManager; +import android.app.PendingIntent; import android.content.ClipboardManager; import android.content.Intent; import android.os.Bundle; @@ -7,25 +9,41 @@ import android.support.v7.app.ActionBar; import android.support.v7.app.AlertDialog.Builder; import android.text.Editable; import android.text.TextWatcher; +import android.util.Log; import android.view.MenuItem; import android.widget.Button; import android.widget.EditText; +import org.briarproject.bramble.api.db.DbException; +import org.briarproject.bramble.api.system.Clock; import org.briarproject.briar.R; import org.briarproject.briar.android.activity.ActivityComponent; import org.briarproject.briar.android.activity.BriarActivity; import org.briarproject.briar.android.navdrawer.NavDrawerActivity; +import org.briarproject.briar.api.messaging.MessagingManager; + +import java.util.Random; import javax.annotation.Nullable; +import javax.inject.Inject; +import static android.app.AlarmManager.ELAPSED_REALTIME; import static android.content.ClipDescription.MIMETYPE_TEXT_PLAIN; import static android.content.Intent.ACTION_SEND; import static android.content.Intent.EXTRA_TEXT; +import static android.os.SystemClock.elapsedRealtime; import static java.util.Objects.requireNonNull; +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.concurrent.TimeUnit.MINUTES; public class ContactLinkInputActivity extends BriarActivity implements TextWatcher { + @Inject + MessagingManager messagingManager; + @Inject + Clock clock; + private ClipboardManager clipboard; private EditText linkInput; private Button pasteButton; @@ -67,6 +85,10 @@ public class ContactLinkInputActivity extends BriarActivity if (i != null && ACTION_SEND.equals(i.getAction())) { String text = i.getStringExtra(EXTRA_TEXT); if (text != null) linkInput.setText(text); + } else if (i != null && "addContact".equals(i.getAction())) { + removeFakeRequest(i.getStringExtra("name"), + i.getLongExtra("timestamp", 0)); + finish(); } } @@ -139,7 +161,38 @@ public class ContactLinkInputActivity extends BriarActivity } private void addFakeRequest() { - // TODO + String name = contactNameInput.getText().toString(); + long timestamp = clock.currentTimeMillis(); + try { + messagingManager.addNewPendingContact(name, timestamp); + } catch (DbException e) { + e.printStackTrace(); + } + + AlarmManager alarmManager = + (AlarmManager) requireNonNull(getSystemService(ALARM_SERVICE)); + long m = MINUTES.toMillis(1); + long fromNow = (long) (-m * Math.log(new Random().nextDouble())); + long triggerAt = elapsedRealtime() + fromNow; + + Intent i = new Intent(this, ContactLinkInputActivity.class); + i.setAction("addContact"); + i.putExtra("name", name); + i.putExtra("timestamp", timestamp); + PendingIntent pendingIntent = PendingIntent.getActivity(this, 42, i, 0); + alarmManager.set(ELAPSED_REALTIME, triggerAt, pendingIntent); + + Log.e("TEST", "Setting Alarm in " + MILLISECONDS.toSeconds(fromNow) + " seconds"); + Log.e("TEST", "with contact: " + name); + } + + private void removeFakeRequest(String name, long timestamp) { + Log.e("TEST", "Adding Contact " + name); + try { + messagingManager.removePendingContact(name, timestamp); + } catch (DbException e) { + e.printStackTrace(); + } } } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactListFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactListFragment.java index 972804d05..64df67de0 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactListFragment.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactListFragment.java @@ -21,6 +21,7 @@ import com.leinardi.android.speeddial.SpeedDialView; import org.briarproject.bramble.api.contact.Contact; import org.briarproject.bramble.api.contact.ContactId; import org.briarproject.bramble.api.contact.ContactManager; +import org.briarproject.bramble.api.contact.event.ContactAddedEvent; import org.briarproject.bramble.api.contact.event.ContactRemovedEvent; import org.briarproject.bramble.api.contact.event.ContactStatusChangedEvent; import org.briarproject.bramble.api.db.DbException; @@ -42,10 +43,13 @@ import org.briarproject.briar.android.view.BriarRecyclerView; import org.briarproject.briar.api.android.AndroidNotificationManager; import org.briarproject.briar.api.client.MessageTracker.GroupCount; import org.briarproject.briar.api.messaging.ConversationManager; +import org.briarproject.briar.api.messaging.MessagingManager; +import org.briarproject.briar.api.messaging.MessagingManager.PendingContact; import org.briarproject.briar.api.messaging.PrivateMessageHeader; import org.briarproject.briar.api.messaging.event.PrivateMessageReceivedEvent; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.logging.Logger; @@ -77,6 +81,10 @@ public class ContactListFragment extends BaseFragment implements EventListener, @Inject AndroidNotificationManager notificationManager; + // TODO remove + @Inject + MessagingManager messagingManager; + private ContactListAdapter adapter; private BriarRecyclerView list; private Snackbar snackbar; @@ -216,7 +224,25 @@ public class ContactListFragment extends BaseFragment implements EventListener, loadContacts(); list.startPeriodicUpdate(); - snackbar.show(); + // TODO remove + checkForPendingContacts(); + } + + // TODO remove + private void checkForPendingContacts() { + listener.runOnDbThread(() -> { + try { + Collection contacts = + messagingManager.getPendingContacts(); + if (contacts.isEmpty()) { + runOnUiThreadUnlessDestroyed(() -> snackbar.dismiss()); + } else { + runOnUiThreadUnlessDestroyed(() -> snackbar.show()); + } + } catch (DbException e) { + e.printStackTrace(); + } + }); } @Override @@ -291,6 +317,11 @@ public class ContactListFragment extends BaseFragment implements EventListener, PrivateMessageHeader h = p.getMessageHeader(); updateItem(p.getContactId(), h); } + + // TODO remove + else if (e instanceof ContactAddedEvent) { + checkForPendingContacts(); + } } private void updateItem(ContactId c, PrivateMessageHeader h) { diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/PendingRequestsActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/PendingRequestsActivity.java index 8c3b64850..a26458ee4 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/contact/PendingRequestsActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/PendingRequestsActivity.java @@ -5,14 +5,34 @@ import android.support.v7.app.ActionBar; import android.support.v7.widget.LinearLayoutManager; import android.view.MenuItem; +import org.briarproject.bramble.api.contact.Contact; +import org.briarproject.bramble.api.contact.ContactManager; +import org.briarproject.bramble.api.contact.event.ContactAddedEvent; +import org.briarproject.bramble.api.db.DbException; +import org.briarproject.bramble.api.event.Event; +import org.briarproject.bramble.api.event.EventBus; +import org.briarproject.bramble.api.event.EventListener; import org.briarproject.briar.R; import org.briarproject.briar.android.activity.ActivityComponent; import org.briarproject.briar.android.activity.BriarActivity; import org.briarproject.briar.android.view.BriarRecyclerView; +import org.briarproject.briar.api.messaging.MessagingManager; +import org.briarproject.briar.api.messaging.MessagingManager.PendingContact; + +import java.util.Collection; import javax.annotation.Nullable; +import javax.inject.Inject; -public class PendingRequestsActivity extends BriarActivity { +public class PendingRequestsActivity extends BriarActivity + implements EventListener { + + @Inject + MessagingManager messagingManager; + @Inject + ContactManager contactManager; + @Inject + EventBus eventBus; private PendingRequestsAdapter adapter; private BriarRecyclerView list; @@ -33,12 +53,31 @@ public class PendingRequestsActivity extends BriarActivity { ab.setDisplayHomeAsUpEnabled(true); } - adapter = new PendingRequestsAdapter(this, PendingRequestsItem.class); + adapter = new PendingRequestsAdapter(this, PendingContact.class); list = findViewById(R.id.list); list.setLayoutManager(new LinearLayoutManager(this)); list.setAdapter(adapter); + } - adapter.add(new PendingRequestsItem("test", System.currentTimeMillis() - 50000)); + @Override + public void onStart() { + super.onStart(); + eventBus.addListener(this); + runOnDbThread(() -> { + try { + Collection contacts = + messagingManager.getPendingContacts(); + addPendingContacts(contacts); + } catch (DbException e) { + e.printStackTrace(); + } + }); + } + + @Override + protected void onStop() { + super.onStop(); + adapter.clear(); } @Override @@ -52,4 +91,32 @@ public class PendingRequestsActivity extends BriarActivity { } } + @Override + public void eventOccurred(Event e) { + if (e instanceof ContactAddedEvent) { + runOnDbThread(() -> { + try { + Contact contact = contactManager + .getContact(((ContactAddedEvent) e).getContactId()); + runOnUiThreadUnlessDestroyed(() -> { + adapter.remove(contact); + if (adapter.isEmpty()) finish(); + }); + } catch (DbException e1) { + e1.printStackTrace(); + } + }); + } + } + + private void addPendingContacts(Collection contacts) { + runOnUiThreadUnlessDestroyed(() -> { + if (contacts.isEmpty()) { + list.showData(); + } else { + adapter.addAll(contacts); + } + }); + } + } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/PendingRequestsAdapter.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/PendingRequestsAdapter.java index c9ba088e6..100e51eaf 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/contact/PendingRequestsAdapter.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/PendingRequestsAdapter.java @@ -6,15 +6,17 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import org.briarproject.bramble.api.contact.Contact; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.briar.R; import org.briarproject.briar.android.util.BriarAdapter; +import org.briarproject.briar.api.messaging.MessagingManager.PendingContact; @NotNullByDefault public class PendingRequestsAdapter extends - BriarAdapter { + BriarAdapter { - public PendingRequestsAdapter(Context ctx, Class c) { + public PendingRequestsAdapter(Context ctx, Class c) { super(ctx, c); } @@ -34,22 +36,32 @@ public class PendingRequestsAdapter extends } @Override - public int compare(PendingRequestsItem item1, PendingRequestsItem item2) { + public int compare(PendingContact item1, PendingContact item2) { return (int) (item1.getTimestamp() - item2.getTimestamp()); } @Override - public boolean areContentsTheSame(PendingRequestsItem item1, - PendingRequestsItem item2) { + public boolean areContentsTheSame(PendingContact item1, + PendingContact item2) { return item1.getName().equals(item2.getName()) && item1.getTimestamp() == item2.getTimestamp(); } @Override - public boolean areItemsTheSame(PendingRequestsItem item1, - PendingRequestsItem item2) { + public boolean areItemsTheSame(PendingContact item1, + PendingContact item2) { return item1.getName().equals(item2.getName()) && item1.getTimestamp() == item2.getTimestamp(); } + // TODO remove + public void remove(Contact contact) { + for (int i = 0; i < items.size(); i++) { + if (items.get(i).getName().equals(contact.getAuthor().getName())) { + items.removeItemAt(i); + return; + } + } + } + } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/PendingRequestsItem.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/PendingRequestsItem.java deleted file mode 100644 index f75b38ef9..000000000 --- a/briar-android/src/main/java/org/briarproject/briar/android/contact/PendingRequestsItem.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.briarproject.briar.android.contact; - -import org.briarproject.bramble.api.nullsafety.NotNullByDefault; - -import javax.annotation.concurrent.Immutable; - -@Immutable -@NotNullByDefault -public class PendingRequestsItem { - - private final String name; - private final long timestamp; - - public PendingRequestsItem(String name, long timestamp) { - this.name = name; - this.timestamp = timestamp; - } - - public String getName() { - return name; - } - - public long getTimestamp() { - return timestamp; - } - -} diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/PendingRequestsViewHolder.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/PendingRequestsViewHolder.java index e83104181..4dd8ba964 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/contact/PendingRequestsViewHolder.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/PendingRequestsViewHolder.java @@ -6,22 +6,29 @@ import android.widget.TextView; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.briar.R; +import org.briarproject.briar.android.view.TextAvatarView; +import org.briarproject.briar.api.messaging.MessagingManager.PendingContact; +import static org.briarproject.bramble.util.StringUtils.toUtf8; import static org.briarproject.briar.android.util.UiUtils.formatDate; @NotNullByDefault public class PendingRequestsViewHolder extends ViewHolder { + private final TextAvatarView avatar; private final TextView name; private final TextView time; public PendingRequestsViewHolder(View v) { super(v); + avatar = v.findViewById(R.id.avatar); name = v.findViewById(R.id.name); time = v.findViewById(R.id.time); } - public void bind(PendingRequestsItem item) { + public void bind(PendingContact item) { + avatar.setText(item.getName()); + avatar.setBackgroundBytes(toUtf8(item.getName())); name.setText(item.getName()); time.setText(formatDate(time.getContext(), item.getTimestamp())); } diff --git a/briar-android/src/main/res/layout/list_item_pending_contact.xml b/briar-android/src/main/res/layout/list_item_pending_contact.xml index 76243d4c9..eed9743fc 100644 --- a/briar-android/src/main/res/layout/list_item_pending_contact.xml +++ b/briar-android/src/main/res/layout/list_item_pending_contact.xml @@ -7,40 +7,75 @@ android:layout_width="match_parent" android:layout_height="wrap_content"> + + + + + app:layout_constraintStart_toEndOf="@+id/avatar"/> - \ 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 5f7d8cbf9..fff763b6a 100644 --- a/briar-android/src/main/res/values/strings.xml +++ b/briar-android/src/main/res/values/strings.xml @@ -167,6 +167,7 @@ Did you send your link already? Yes No + Connecting… Introduce your contacts diff --git a/briar-api/src/main/java/org/briarproject/briar/api/messaging/MessagingManager.java b/briar-api/src/main/java/org/briarproject/briar/api/messaging/MessagingManager.java index 47c4f66b0..786958a18 100644 --- a/briar-api/src/main/java/org/briarproject/briar/api/messaging/MessagingManager.java +++ b/briar-api/src/main/java/org/briarproject/briar/api/messaging/MessagingManager.java @@ -8,9 +8,31 @@ import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.briar.api.messaging.ConversationManager.ConversationClient; +import java.util.Collection; + @NotNullByDefault public interface MessagingManager extends ConversationClient { + // TODO remove (only for prototype) + void addNewPendingContact(String name, long timestamp) throws DbException; + void removePendingContact(String name, long timestamp) throws DbException; + Collection getPendingContacts() throws DbException; + class PendingContact { + private final String name; + private final long timestamp; + public PendingContact(String name, long timestamp) { + this.name = name; + this.timestamp = timestamp; + } + public String getName() { + return name; + } + public long getTimestamp() { + return timestamp; + } + } + + /** * The unique ID of the messaging client. */ diff --git a/briar-core/src/main/java/org/briarproject/briar/messaging/MessagingManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/messaging/MessagingManagerImpl.java index cf97a32b2..535dd384e 100644 --- a/briar-core/src/main/java/org/briarproject/briar/messaging/MessagingManagerImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/messaging/MessagingManagerImpl.java @@ -5,13 +5,19 @@ import org.briarproject.bramble.api.client.ClientHelper; import org.briarproject.bramble.api.client.ContactGroupFactory; import org.briarproject.bramble.api.contact.Contact; import org.briarproject.bramble.api.contact.ContactId; +import org.briarproject.bramble.api.contact.ContactManager; import org.briarproject.bramble.api.contact.ContactManager.ContactHook; import org.briarproject.bramble.api.data.BdfDictionary; +import org.briarproject.bramble.api.data.BdfEntry; import org.briarproject.bramble.api.data.BdfList; import org.briarproject.bramble.api.data.MetadataParser; import org.briarproject.bramble.api.db.DatabaseComponent; import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.Transaction; +import org.briarproject.bramble.api.identity.Author; +import org.briarproject.bramble.api.identity.AuthorFactory; +import org.briarproject.bramble.api.identity.AuthorId; +import org.briarproject.bramble.api.identity.IdentityManager; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.sync.Client; import org.briarproject.bramble.api.sync.Group; @@ -23,6 +29,7 @@ import org.briarproject.bramble.api.sync.MessageStatus; import org.briarproject.bramble.api.versioning.ClientVersioningManager; import org.briarproject.bramble.api.versioning.ClientVersioningManager.ClientVersioningHook; import org.briarproject.briar.api.client.MessageTracker; +import org.briarproject.briar.api.introduction.event.IntroductionSucceededEvent; import org.briarproject.briar.api.messaging.MessagingManager; import org.briarproject.briar.api.messaging.PrivateMessage; import org.briarproject.briar.api.messaging.PrivateMessageHeader; @@ -31,11 +38,13 @@ import org.briarproject.briar.client.ConversationClientImpl; import java.util.ArrayList; import java.util.Collection; +import java.util.List; import java.util.Map; import javax.annotation.concurrent.Immutable; import javax.inject.Inject; +import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH; import static org.briarproject.briar.client.MessageTrackerConstants.MSG_KEY_READ; @Immutable @@ -46,14 +55,114 @@ class MessagingManagerImpl extends ConversationClientImpl private final ClientVersioningManager clientVersioningManager; private final ContactGroupFactory contactGroupFactory; + // TODO remove + private final ContactManager contactManager; + private final IdentityManager identityManager; + private final AuthorFactory authorFactory; + @Inject MessagingManagerImpl(DatabaseComponent db, ClientHelper clientHelper, ClientVersioningManager clientVersioningManager, MetadataParser metadataParser, MessageTracker messageTracker, - ContactGroupFactory contactGroupFactory) { + ContactGroupFactory contactGroupFactory, + ContactManager contactManager, IdentityManager identityManager, + AuthorFactory authorFactory) { super(db, clientHelper, metadataParser, messageTracker); this.clientVersioningManager = clientVersioningManager; this.contactGroupFactory = contactGroupFactory; + + // TODO remove + this.contactManager = contactManager; + this.identityManager = identityManager; + this.authorFactory = authorFactory; + } + + private static final String PENDING_CONTACTS = "PENDING_CONTACTS"; + @Override + public void addNewPendingContact(String name, long timestamp) + throws DbException { + Transaction txn = db.startTransaction(false); + try { + BdfList list = getPendingContacts(txn); + BdfDictionary contact = new BdfDictionary(); + contact.put("name", name); + contact.put("timestamp", timestamp); + list.add(contact); + + Group localGroup = contactGroupFactory.createLocalGroup(CLIENT_ID, + MAJOR_VERSION); + BdfDictionary meta = + BdfDictionary.of(new BdfEntry(PENDING_CONTACTS, list)); + clientHelper.mergeGroupMetadata(txn, localGroup.getId(), meta); + + db.commitTransaction(txn); + } catch (FormatException e) { + throw new RuntimeException(e); + } finally { + db.endTransaction(txn); + } + } + @Override + public void removePendingContact(String name, long timestamp) throws DbException { + Transaction txn = db.startTransaction(false); + try { + BdfList list = getPendingContacts(txn); + + BdfDictionary contactDict = new BdfDictionary(); + contactDict.put("name", name); + contactDict.put("timestamp", timestamp); + list.remove(contactDict); + + Group localGroup = contactGroupFactory.createLocalGroup(CLIENT_ID, + MAJOR_VERSION); + BdfDictionary meta = + BdfDictionary.of(new BdfEntry(PENDING_CONTACTS, list)); + clientHelper.mergeGroupMetadata(txn, localGroup.getId(), meta); + + AuthorId local = identityManager.getLocalAuthor(txn).getId(); + Author remote = authorFactory + .createAuthor(name, new byte[MAX_PUBLIC_KEY_LENGTH]); + contactManager.addContact(txn, remote, local, false, true); + + Contact contact = + contactManager.getContact(txn, remote.getId(), local); + IntroductionSucceededEvent event = + new IntroductionSucceededEvent(contact); + txn.attach(event); + + db.commitTransaction(txn); + } catch (FormatException e) { + throw new RuntimeException(e); + } finally { + db.endTransaction(txn); + } + } + @Override + public Collection getPendingContacts() throws DbException { + Transaction txn = db.startTransaction(true); + try { + BdfList list = getPendingContacts(txn); + List contacts = new ArrayList<>(list.size()); + for (Object o : list) { + BdfDictionary d = (BdfDictionary) o; + contacts.add(new PendingContact(d.getString("name"), + d.getLong("timestamp"))); + } + db.commitTransaction(txn); + return contacts; + } catch (FormatException e) { + throw new RuntimeException(e); + } finally { + db.endTransaction(txn); + } + } + private BdfList getPendingContacts(Transaction txn) + throws DbException, FormatException { + Group localGroup = contactGroupFactory.createLocalGroup(CLIENT_ID, + MAJOR_VERSION); + BdfDictionary d = clientHelper + .getGroupMetadataAsDictionary(txn, localGroup.getId()); + return d.getList(PENDING_CONTACTS, new BdfList()); } @Override