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 f864fa7f371d393139fc4a87353ef6495a8ee5db..e6be9a4d2f61956d238ab6e147761e766b307a33 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 @@ -43,6 +43,24 @@ public interface ContactManager { */ Contact getContact(ContactId c) throws DbException; + /** + * Returns the contact with the given remoteAuthorId + * that was added by the LocalAuthor with the given localAuthorId + * + * @throws org.briarproject.bramble.api.db.NoSuchContactException + */ + Contact getContact(AuthorId remoteAuthorId, AuthorId localAuthorId) + throws DbException; + + /** + * Returns the contact with the given remoteAuthorId + * that was added by the LocalAuthor with the given localAuthorId + * + * @throws org.briarproject.bramble.api.db.NoSuchContactException + */ + Contact getContact(Transaction txn, AuthorId remoteAuthorId, + AuthorId localAuthorId) throws DbException; + /** * Returns all active contacts. */ 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 c4c3152b7a6d65fbc295bdc57e1b5d21c7d48fda..c840321365c62b5617479e9e8e9c547d06a486f0 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 @@ -6,6 +6,7 @@ import org.briarproject.bramble.api.contact.ContactManager; import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.db.DatabaseComponent; import org.briarproject.bramble.api.db.DbException; +import org.briarproject.bramble.api.db.NoSuchContactException; import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.AuthorId; @@ -88,6 +89,32 @@ class ContactManagerImpl implements ContactManager { return contact; } + @Override + public Contact getContact(AuthorId remoteAuthorId, AuthorId localAuthorId) + throws DbException { + Transaction txn = db.startTransaction(true); + try { + Contact c = getContact(txn, remoteAuthorId, localAuthorId); + db.commitTransaction(txn); + return c; + } finally { + db.endTransaction(txn); + } + } + + @Override + public Contact getContact(Transaction txn, AuthorId remoteAuthorId, + AuthorId localAuthorId) throws DbException { + Collection<Contact> contacts = + db.getContactsByAuthorId(txn, remoteAuthorId); + for (Contact c : contacts) { + if (c.getLocalAuthorId().equals(localAuthorId)) { + return c; + } + } + throw new NoSuchContactException(); + } + @Override public Collection<Contact> getActiveContacts() throws DbException { Collection<Contact> contacts; diff --git a/briar-android-tests/src/test/java/org/briarproject/BlogSharingIntegrationTest.java b/briar-android-tests/src/test/java/org/briarproject/BlogSharingIntegrationTest.java index 538cf3ccf9b761735469526657603d06bbb62244..4e010620f462050aa88e2b865b54cb09de1ab5bc 100644 --- a/briar-android-tests/src/test/java/org/briarproject/BlogSharingIntegrationTest.java +++ b/briar-android-tests/src/test/java/org/briarproject/BlogSharingIntegrationTest.java @@ -4,6 +4,7 @@ import net.jodah.concurrentunit.Waiter; import org.briarproject.bramble.api.contact.Contact; import org.briarproject.bramble.api.db.DbException; +import org.briarproject.bramble.api.db.NoSuchGroupException; import org.briarproject.bramble.api.event.Event; import org.briarproject.bramble.api.event.EventListener; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; @@ -30,6 +31,7 @@ import static org.briarproject.briar.api.blog.BlogSharingManager.CLIENT_ID; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; public class BlogSharingIntegrationTest extends BriarIntegrationTest<BriarIntegrationTestComponent> { @@ -266,7 +268,7 @@ public class BlogSharingIntegrationTest assertTrue(blogSharingManager0.getSharedWith(blog2.getId()) .contains(contact1From0)); // invitee gets blog shared by sharer - assertTrue(blogSharingManager1.getSharedBy(blog2.getId()) + assertTrue(blogSharingManager1.getSharedWith(blog2.getId()) .contains(contact0From1)); // invitee un-subscribes from blog @@ -282,9 +284,13 @@ public class BlogSharingIntegrationTest // sharer no longer shares blog with invitee assertFalse(blogSharingManager0.getSharedWith(blog2.getId()) .contains(contact1From0)); - // invitee no longer gets blog shared by sharer - assertFalse(blogSharingManager1.getSharedBy(blog2.getId()) - .contains(contact0From1)); + // invitee no longer has blog shared by sharer + try { + blogSharingManager1.getSharedWith(blog2.getId()); + fail(); + } catch (NoSuchGroupException e) { + // expected + } // blog can be shared again assertTrue( blogSharingManager0.canBeShared(blog2.getId(), contact1From0)); @@ -310,10 +316,10 @@ public class BlogSharingIntegrationTest eventWaiter.await(TIMEOUT, 1); assertTrue(listener1.requestReceived); - // make sure blog2 is shared by 0 + // make sure blog2 is shared by 0 and 2 Collection<Contact> contacts = - blogSharingManager1.getSharedBy(blog2.getId()); - assertEquals(1, contacts.size()); + blogSharingManager1.getSharedWith(blog2.getId()); + assertEquals(2, contacts.size()); assertTrue(contacts.contains(contact0From1)); // make sure 1 knows that they have blog2 already @@ -355,10 +361,11 @@ public class BlogSharingIntegrationTest assertEquals(3, blogManager1.getBlogs().size()); Collection<Contact> sharedWith = blogSharingManager0.getSharedWith(blog2.getId()); - assertEquals(1, sharedWith.size()); - assertEquals(contact1From0, sharedWith.iterator().next()); + assertEquals(2, sharedWith.size()); + assertTrue(sharedWith.contains(contact1From0)); + assertTrue(sharedWith.contains(contact2From0)); Collection<Contact> sharedBy = - blogSharingManager1.getSharedBy(blog2.getId()); + blogSharingManager1.getSharedWith(blog2.getId()); assertEquals(1, sharedBy.size()); assertEquals(contact0From1, sharedBy.iterator().next()); @@ -374,7 +381,8 @@ public class BlogSharingIntegrationTest // sharer does not share this blog anymore with invitee sharedWith = blogSharingManager0.getSharedWith(blog2.getId()); - assertEquals(0, sharedWith.size()); + assertEquals(1, sharedWith.size()); + assertTrue(sharedWith.contains(contact2From0)); } @Test @@ -396,7 +404,7 @@ public class BlogSharingIntegrationTest // make sure blog2 is shared by 0 Collection<Contact> contacts = - blogSharingManager1.getSharedBy(blog2.getId()); + blogSharingManager1.getSharedWith(blog2.getId()); assertEquals(1, contacts.size()); assertTrue(contacts.contains(contact0From1)); diff --git a/briar-android-tests/src/test/java/org/briarproject/ForumSharingIntegrationTest.java b/briar-android-tests/src/test/java/org/briarproject/ForumSharingIntegrationTest.java index 40e3f0103f00f63da54b8cb5716a8f0c8eeebbb2..b701f77f821bb72505611f9c96281029c5ea36e5 100644 --- a/briar-android-tests/src/test/java/org/briarproject/ForumSharingIntegrationTest.java +++ b/briar-android-tests/src/test/java/org/briarproject/ForumSharingIntegrationTest.java @@ -244,7 +244,7 @@ public class ForumSharingIntegrationTest .contains(c1)); // invitee gets forum shared by sharer Contact contact0 = contactManager1.getContact(contactId1From0); - assertTrue(forumSharingManager1.getSharedBy(forum0.getId()) + assertTrue(forumSharingManager1.getSharedWith(forum0.getId()) .contains(contact0)); // invitee un-subscribes from forum @@ -261,7 +261,7 @@ public class ForumSharingIntegrationTest assertFalse(forumSharingManager0.getSharedWith(forum0.getId()) .contains(c1)); // invitee no longer gets forum shared by sharer - assertFalse(forumSharingManager1.getSharedBy(forum0.getId()) + assertFalse(forumSharingManager1.getSharedWith(forum0.getId()) .contains(contact0)); // forum can be shared again assertTrue(forumSharingManager0.canBeShared(forum0.getId(), c1)); @@ -299,7 +299,7 @@ public class ForumSharingIntegrationTest .contains(c1)); // invitee gets forum shared by sharer Contact contact0 = contactManager1.getContact(contactId1From0); - assertTrue(forumSharingManager1.getSharedBy(forum0.getId()) + assertTrue(forumSharingManager1.getSharedWith(forum0.getId()) .contains(contact0)); // sharer un-subscribes from forum @@ -317,7 +317,7 @@ public class ForumSharingIntegrationTest assertFalse(forumSharingManager1.getSharedWith(forum0.getId()) .contains(c0)); // sharer no longer gets forum shared by invitee - assertFalse(forumSharingManager1.getSharedBy(forum0.getId()) + assertFalse(forumSharingManager1.getSharedWith(forum0.getId()) .contains(contact0)); // forum can be shared again assertTrue(forumSharingManager1.canBeShared(forum0.getId(), c0)); @@ -647,11 +647,11 @@ public class ForumSharingIntegrationTest assertEquals(2, forums.iterator().next().getNewSharers().size()); assertEquals(forum0, forums.iterator().next().getShareable()); assertEquals(2, - forumSharingManager1.getSharedBy(forum0.getId()).size()); + forumSharingManager1.getSharedWith(forum0.getId()).size()); // make sure both sharers actually share the forum Collection<Contact> contacts = - forumSharingManager1.getSharedBy(forum0.getId()); + forumSharingManager1.getSharedWith(forum0.getId()); assertEquals(2, contacts.size()); // answer second request diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactItem.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactItem.java index 720a9d6df33ddc445b32af1ea2a7121d8a589655..703835a3bcfcaade19eb3d845a6197faf7c32e7e 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactItem.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactItem.java @@ -10,13 +10,27 @@ import javax.annotation.concurrent.NotThreadSafe; public class ContactItem { private final Contact contact; + private boolean connected; public ContactItem(Contact contact) { this.contact = contact; } + public ContactItem(Contact contact, boolean connected) { + this.contact = contact; + this.connected = connected; + } + public Contact getContact() { return contact; } + boolean isConnected() { + return connected; + } + + void setConnected(boolean connected) { + this.connected = connected; + } + } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactItemViewHolder.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactItemViewHolder.java index 3791c6c34323906fb09e0b8b238374ec78acaeb2..3b543a19eeb6502453de0a523426c5d9b889342b 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactItemViewHolder.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactItemViewHolder.java @@ -1,5 +1,6 @@ package org.briarproject.briar.android.contact; +import android.support.annotation.Nullable; import android.support.annotation.UiThread; import android.support.v7.widget.RecyclerView; import android.view.View; @@ -12,8 +13,6 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.briar.R; import org.briarproject.briar.android.contact.BaseContactListAdapter.OnContactClickListener; -import javax.annotation.Nullable; - import im.delight.android.identicons.IdenticonDrawable; @UiThread @@ -24,6 +23,8 @@ public class ContactItemViewHolder<I extends ContactItem> protected final ViewGroup layout; protected final ImageView avatar; protected final TextView name; + @Nullable + protected final ImageView bulb; public ContactItemViewHolder(View v) { super(v); @@ -31,6 +32,7 @@ public class ContactItemViewHolder<I extends ContactItem> layout = (ViewGroup) v; avatar = (ImageView) v.findViewById(R.id.avatarView); name = (TextView) v.findViewById(R.id.nameView); + bulb = (ImageView) v.findViewById(R.id.bulbView); } protected void bind(final I item, @@ -41,6 +43,15 @@ public class ContactItemViewHolder<I extends ContactItem> String contactName = author.getName(); name.setText(contactName); + if (bulb != null) { + // online/offline + if (item.isConnected()) { + bulb.setImageResource(R.drawable.contact_connected); + } else { + bulb.setImageResource(R.drawable.contact_disconnected); + } + } + layout.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactListItem.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactListItem.java index d6e839afa69083571fb92a33e2222e370a3b50b5..c8e47207c949d4e9335dd649283b7f5ba7497b5d 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactListItem.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactListItem.java @@ -10,14 +10,13 @@ import javax.annotation.concurrent.NotThreadSafe; @NotNullByDefault public class ContactListItem extends ContactItem { - private boolean connected, empty; + private boolean empty; private long timestamp; private int unread; public ContactListItem(Contact contact, boolean connected, GroupCount count) { - super(contact); - this.connected = connected; + super(contact, connected); this.empty = count.getMsgCount() == 0; this.unread = count.getUnreadCount(); this.timestamp = count.getLatestMsgTime(); @@ -30,14 +29,6 @@ public class ContactListItem extends ContactItem { unread++; } - boolean isConnected() { - return connected; - } - - void setConnected(boolean connected) { - this.connected = connected; - } - boolean isEmpty() { return empty; } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactListItemViewHolder.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactListItemViewHolder.java index 649e3782f98474b9ded132d372f11687edd06752..386b2590620ef8a648019525b926d9cd1c4e1037 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactListItemViewHolder.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactListItemViewHolder.java @@ -2,7 +2,6 @@ package org.briarproject.briar.android.contact; import android.support.annotation.UiThread; import android.view.View; -import android.widget.ImageView; import android.widget.TextView; import org.briarproject.bramble.api.contact.ContactId; @@ -20,13 +19,11 @@ import static org.briarproject.briar.android.util.UiUtils.formatDate; @NotNullByDefault class ContactListItemViewHolder extends ContactItemViewHolder<ContactListItem> { - protected final ImageView bulb; private final TextView unread; private final TextView date; ContactListItemViewHolder(View v) { super(v); - bulb = (ImageView) v.findViewById(R.id.bulbView); unread = (TextView) v.findViewById(R.id.unreadCountView); date = (TextView) v.findViewById(R.id.dateView); } @@ -53,13 +50,6 @@ class ContactListItemViewHolder extends ContactItemViewHolder<ContactListItem> { date.setText(formatDate(date.getContext(), timestamp)); } - // online/offline - if (item.isConnected()) { - bulb.setImageResource(R.drawable.contact_connected); - } else { - bulb.setImageResource(R.drawable.contact_disconnected); - } - ContactId c = item.getContact().getId(); setTransitionName(avatar, UiUtils.getAvatarTransitionName(c)); setTransitionName(bulb, UiUtils.getBulbTransitionName(c)); diff --git a/briar-android/src/main/java/org/briarproject/briar/android/sharing/BlogSharingStatusActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/sharing/BlogSharingStatusActivity.java index ab60768c674f3a0b88ada18277aebb87b18768a1..a1adeace5593457397fdd3e1645886a62724cb48 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/sharing/BlogSharingStatusActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/sharing/BlogSharingStatusActivity.java @@ -3,6 +3,8 @@ package org.briarproject.briar.android.sharing; import org.briarproject.bramble.api.contact.Contact; import org.briarproject.bramble.api.db.DatabaseExecutor; import org.briarproject.bramble.api.db.DbException; +import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; +import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; import org.briarproject.briar.android.activity.ActivityComponent; import org.briarproject.briar.api.blog.BlogSharingManager; @@ -10,6 +12,8 @@ import java.util.Collection; import javax.inject.Inject; +@MethodsNotNullByDefault +@ParametersNotNullByDefault public class BlogSharingStatusActivity extends SharingStatusActivity { // Fields that are accessed from background threads must be volatile @@ -21,16 +25,10 @@ public class BlogSharingStatusActivity extends SharingStatusActivity { component.inject(this); } - @DatabaseExecutor @Override + @DatabaseExecutor protected Collection<Contact> getSharedWith() throws DbException { return blogSharingManager.getSharedWith(getGroupId()); } - @DatabaseExecutor - @Override - protected Collection<Contact> getSharedBy() throws DbException { - return blogSharingManager.getSharedBy(getGroupId()); - } - } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/sharing/ForumSharingStatusActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/sharing/ForumSharingStatusActivity.java index fc59fd9cfdea77d7f9de067e605a76157d759c47..e9edf9e839916bb2e935533ec6d111784d99ab47 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/sharing/ForumSharingStatusActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/sharing/ForumSharingStatusActivity.java @@ -3,13 +3,18 @@ package org.briarproject.briar.android.sharing; import org.briarproject.bramble.api.contact.Contact; import org.briarproject.bramble.api.db.DatabaseExecutor; import org.briarproject.bramble.api.db.DbException; +import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; +import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; import org.briarproject.briar.android.activity.ActivityComponent; import org.briarproject.briar.api.forum.ForumSharingManager; import java.util.Collection; +import java.util.HashSet; import javax.inject.Inject; +@MethodsNotNullByDefault +@ParametersNotNullByDefault public class ForumSharingStatusActivity extends SharingStatusActivity { // Fields that are accessed from background threads must be volatile @@ -21,16 +26,10 @@ public class ForumSharingStatusActivity extends SharingStatusActivity { component.inject(this); } - @DatabaseExecutor @Override + @DatabaseExecutor protected Collection<Contact> getSharedWith() throws DbException { return forumSharingManager.getSharedWith(getGroupId()); } - @DatabaseExecutor - @Override - protected Collection<Contact> getSharedBy() throws DbException { - return forumSharingManager.getSharedBy(getGroupId()); - } - } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/sharing/SharingStatusActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/sharing/SharingStatusActivity.java index 543aaf6cd8f27efaae03f092d469e53015a62c8d..db72e8c55cbcb9cf66967e7884a488d6d8f5acfe 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/sharing/SharingStatusActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/sharing/SharingStatusActivity.java @@ -2,11 +2,16 @@ package org.briarproject.briar.android.sharing; import android.content.Intent; import android.os.Bundle; +import android.support.annotation.Nullable; import android.support.v7.widget.LinearLayoutManager; import android.view.MenuItem; import org.briarproject.bramble.api.contact.Contact; +import org.briarproject.bramble.api.db.DatabaseExecutor; import org.briarproject.bramble.api.db.DbException; +import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; +import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; +import org.briarproject.bramble.api.plugin.ConnectionRegistry; import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.briar.R; import org.briarproject.briar.android.activity.BriarActivity; @@ -18,55 +23,53 @@ import java.util.Collection; import java.util.List; import java.util.logging.Logger; +import javax.inject.Inject; + import static java.util.logging.Level.WARNING; +@MethodsNotNullByDefault +@ParametersNotNullByDefault abstract class SharingStatusActivity extends BriarActivity { + @Inject + ConnectionRegistry connectionRegistry; + private static final Logger LOG = Logger.getLogger(SharingStatusActivity.class.getName()); private GroupId groupId; - private BriarRecyclerView sharedByList, sharedWithList; - private SharingStatusAdapter sharedByAdapter, sharedWithAdapter; + private BriarRecyclerView list; + private SharingStatusAdapter adapter; @Override - public void onCreate(Bundle savedInstanceState) { + public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(R.layout.activity_sharing_status); + setContentView(R.layout.list); Intent i = getIntent(); byte[] b = i.getByteArrayExtra(GROUP_ID); if (b == null) throw new IllegalStateException("No GroupId"); groupId = new GroupId(b); - sharedByList = (BriarRecyclerView) findViewById(R.id.sharedByView); - sharedByAdapter = new SharingStatusAdapter(this); - sharedByList.setLayoutManager(new LinearLayoutManager(this)); - sharedByList.setAdapter(sharedByAdapter); - sharedByList.setEmptyText(getString(R.string.nobody)); - - sharedWithList = (BriarRecyclerView) findViewById(R.id.sharedWithView); - sharedWithAdapter = new SharingStatusAdapter(this); - sharedWithList.setLayoutManager(new LinearLayoutManager(this)); - sharedWithList.setAdapter(sharedWithAdapter); - sharedWithList.setEmptyText(getString(R.string.nobody)); + list = (BriarRecyclerView) findViewById(R.id.list); + adapter = new SharingStatusAdapter(this); + list.setLayoutManager(new LinearLayoutManager(this)); + list.setAdapter(adapter); + list.setEmptyText(getString(R.string.nobody)); } @Override public void onStart() { super.onStart(); - loadSharedBy(); loadSharedWith(); } @Override public void onStop() { super.onStop(); - sharedByAdapter.clear(); - sharedByList.showProgressBar(); - sharedWithAdapter.clear(); - sharedWithList.showProgressBar(); + adapter.clear(); + list.showProgressBar(); } @Override @@ -81,49 +84,13 @@ abstract class SharingStatusActivity extends BriarActivity { } } - /** - * This must only be called from the DbThread - */ + @DatabaseExecutor abstract protected Collection<Contact> getSharedWith() throws DbException; - /** - * This must only be called from the DbThread - */ - abstract protected Collection<Contact> getSharedBy() throws DbException; - protected GroupId getGroupId() { return groupId; } - private void loadSharedBy() { - runOnDbThread(new Runnable() { - @Override - public void run() { - try { - List<ContactItem> contactItems = new ArrayList<>(); - for (Contact c : getSharedBy()) { - ContactItem item = new ContactItem(c); - contactItems.add(item); - } - displaySharedBy(contactItems); - } catch (DbException e) { - if (LOG.isLoggable(WARNING)) - LOG.log(WARNING, e.toString(), e); - } - } - }); - } - - private void displaySharedBy(final List<ContactItem> contacts) { - runOnUiThreadUnlessDestroyed(new Runnable() { - @Override - public void run() { - if (contacts.isEmpty()) sharedByList.showData(); - else sharedByAdapter.addAll(contacts); - } - }); - } - private void loadSharedWith() { runOnDbThread(new Runnable() { @Override @@ -131,7 +98,9 @@ abstract class SharingStatusActivity extends BriarActivity { try { List<ContactItem> contactItems = new ArrayList<>(); for (Contact c : getSharedWith()) { - ContactItem item = new ContactItem(c); + boolean online = + connectionRegistry.isConnected(c.getId()); + ContactItem item = new ContactItem(c, online); contactItems.add(item); } displaySharedWith(contactItems); @@ -147,8 +116,8 @@ abstract class SharingStatusActivity extends BriarActivity { runOnUiThreadUnlessDestroyed(new Runnable() { @Override public void run() { - if (contacts.isEmpty()) sharedWithList.showData(); - else sharedWithAdapter.addAll(contacts); + if (contacts.isEmpty()) list.showData(); + else adapter.addAll(contacts); } }); } diff --git a/briar-android/src/main/res/layout/activity_sharing_status.xml b/briar-android/src/main/res/layout/activity_sharing_status.xml deleted file mode 100644 index ee9153f477e454e0e787ea45f5ea9b848f55144d..0000000000000000000000000000000000000000 --- a/briar-android/src/main/res/layout/activity_sharing_status.xml +++ /dev/null @@ -1,48 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<ScrollView - xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="match_parent"> - - <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="vertical"> - - <TextView - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:background="@color/default_separator_inverted" - android:padding="@dimen/margin_medium" - android:text="@string/forum_shared_by" - android:textSize="@dimen/text_size_large"/> - - <View style="@style/Divider.ForumList"/> - - <org.briarproject.briar.android.view.BriarRecyclerView - android:id="@+id/sharedByView" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:paddingBottom="@dimen/margin_medium" - android:paddingTop="@dimen/margin_medium"/> - - <TextView - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:background="@color/default_separator_inverted" - android:padding="@dimen/margin_medium" - android:text="@string/forum_shared_with" - android:textSize="@dimen/text_size_large"/> - - <View style="@style/Divider.ForumList"/> - - <org.briarproject.briar.android.view.BriarRecyclerView - android:id="@+id/sharedWithView" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:paddingBottom="@dimen/margin_medium" - android:paddingTop="@dimen/margin_medium"/> - - </LinearLayout> - -</ScrollView> \ No newline at end of file diff --git a/briar-android/src/main/res/layout/list_item_contact_small.xml b/briar-android/src/main/res/layout/list_item_contact_small.xml index 66b4c44e38f493469ec224ff39c3363b85af2fb8..742c56c465070f9e18f66151d4a34db3c5fdcd74 100644 --- a/briar-android/src/main/res/layout/list_item_contact_small.xml +++ b/briar-android/src/main/res/layout/list_item_contact_small.xml @@ -5,28 +5,38 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" - android:paddingBottom="@dimen/margin_small" - android:paddingTop="@dimen/margin_small"> + android:paddingBottom="@dimen/margin_medium" + android:paddingTop="@dimen/margin_medium"> <de.hdodenhof.circleimageview.CircleImageView android:id="@+id/avatarView" style="@style/BriarAvatar" android:layout_width="@dimen/listitem_picture_size_small" android:layout_height="@dimen/listitem_picture_size_small" + android:layout_gravity="center_vertical" android:layout_marginLeft="@dimen/listitem_horizontal_margin" android:layout_marginStart="@dimen/listitem_horizontal_margin" tools:src="@drawable/ic_launcher"/> <org.thoughtcrime.securesms.components.emoji.EmojiTextView android:id="@+id/nameView" - android:layout_width="wrap_content" + android:layout_width="0dp" android:layout_height="wrap_content" android:layout_gravity="center_vertical" - android:layout_marginLeft="@dimen/listitem_horizontal_margin" - android:layout_marginStart="@dimen/listitem_horizontal_margin" + android:layout_marginLeft="@dimen/margin_medium" + android:layout_marginStart="@dimen/margin_medium" + android:layout_weight="1" android:maxLines="2" android:textColor="@color/briar_text_primary" android:textSize="@dimen/text_size_medium" tools:text="This is a name of a contact"/> -</LinearLayout> \ No newline at end of file + <ImageView + android:id="@+id/bulbView" + android:layout_width="@dimen/listitem_horizontal_margin" + android:layout_height="@dimen/listitem_horizontal_margin" + android:layout_gravity="center_vertical" + android:layout_marginRight="@dimen/listitem_horizontal_margin" + tools:src="@drawable/contact_connected"/> + +</LinearLayout> diff --git a/briar-android/src/main/res/values/strings.xml b/briar-android/src/main/res/values/strings.xml index e27a3ea9cacd4ed64af3ed35c18b8e7e058c0597..c8e80030db28aab8a0dc9f381c21cf80fbc663b3 100644 --- a/briar-android/src/main/res/values/strings.xml +++ b/briar-android/src/main/res/values/strings.xml @@ -262,8 +262,6 @@ <item quantity="one">%d forum shared by contacts</item> <item quantity="other">%d forums shared by contacts</item> </plurals> - <string name="forum_shared_by">Shared by</string> - <string name="forum_shared_with">Shared with</string> <string name="nobody">Nobody</string> <!-- Blogs --> diff --git a/briar-api/src/main/java/org/briarproject/briar/api/sharing/SharingManager.java b/briar-api/src/main/java/org/briarproject/briar/api/sharing/SharingManager.java index e4cff4876ead3adfe3448cbd2237d0629bcd4d0b..693c0f8b4204a2e3b59e65f011844f2033c4d4f7 100644 --- a/briar-api/src/main/java/org/briarproject/briar/api/sharing/SharingManager.java +++ b/briar-api/src/main/java/org/briarproject/briar/api/sharing/SharingManager.java @@ -47,11 +47,6 @@ public interface SharingManager<S extends Shareable> */ Collection<SharingInvitationItem> getInvitations() throws DbException; - /** - * Returns all contacts who are sharing the given group with us. - */ - Collection<Contact> getSharedBy(GroupId g) throws DbException; - /** * Returns all contacts with whom the given group is shared. */ diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/BlogSharingManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/sharing/BlogSharingManagerImpl.java index b68187b07831d7ed96bf33fc16506ee675560280..ba160b2b5745393155b078383330b8aaa8126fb2 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/BlogSharingManagerImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/BlogSharingManagerImpl.java @@ -5,6 +5,7 @@ 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.data.BdfDictionary; import org.briarproject.bramble.api.data.BdfList; import org.briarproject.bramble.api.data.MetadataEncoder; @@ -37,6 +38,7 @@ import org.briarproject.briar.api.client.SessionId; import org.briarproject.briar.api.sharing.InvitationMessage; import java.security.SecureRandom; +import java.util.Collection; import javax.annotation.concurrent.Immutable; import javax.inject.Inject; @@ -52,6 +54,7 @@ class BlogSharingManagerImpl extends SharingManagerImpl<Blog, BlogInvitation, BlogInviteeSessionState, BlogSharerSessionState, BlogInvitationRequestReceivedEvent, BlogInvitationResponseReceivedEvent> implements BlogSharingManager, RemoveBlogHook { + private final ContactManager contactManager; private final IdentityManager identityManager; private final BlogManager blogManager; @@ -68,13 +71,15 @@ class BlogSharingManagerImpl extends DatabaseComponent db, MessageQueueManager messageQueueManager, MetadataEncoder metadataEncoder, MetadataParser metadataParser, ContactGroupFactory contactGroupFactory, SecureRandom random, - IdentityManager identityManager, MessageTracker messageTracker) { + ContactManager contactManager, IdentityManager identityManager, + MessageTracker messageTracker) { super(db, messageQueueManager, clientHelper, metadataParser, metadataEncoder, random, contactGroupFactory, messageTracker, clock); this.blogManager = blogManager; + this.contactManager = contactManager; this.identityManager = identityManager; sFactory = new SFactory(authorFactory, blogFactory, blogManager); iFactory = new IFactory(); @@ -105,6 +110,27 @@ class BlogSharingManagerImpl extends return super.canBeShared(txn, g, c); } + @Override + public Collection<Contact> getSharedWith(GroupId g) throws DbException { + Blog blog = blogManager.getBlog(g); + LocalAuthor author = identityManager.getLocalAuthor(); + if (blog.getAuthor().equals(author)) { + // This is our personal blog. It is shared with all our contacts + return contactManager.getActiveContacts(); + } else { + // This is someone else's blog. Look up who it is shared with + Collection<Contact> shared = super.getSharedWith(g); + // If the blog author is our contact, also add her to the list + boolean isContact = contactManager + .contactExists(blog.getAuthor().getId(), author.getId()); + if (isContact) { + shared.add(contactManager + .getContact(blog.getAuthor().getId(), author.getId())); + } + return shared; + } + } + @Override protected InvitationMessage createInvitationRequest(MessageId id, BlogInvitation msg, ContactId contactId, boolean available, diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/SharingManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/sharing/SharingManagerImpl.java index 4c99ceb54a5c9742f5e63be0a39619dc0156b37f..c1d54f4f9a9866a74cc568658e7ae0f95af166f8 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/SharingManagerImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/SharingManagerImpl.java @@ -514,34 +514,6 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IS return invited; } - @Override - public Collection<Contact> getSharedBy(GroupId g) throws DbException { - List<Contact> subscribers; - Transaction txn = db.startTransaction(true); - try { - subscribers = getSharedBy(txn, g); - db.commitTransaction(txn); - } finally { - db.endTransaction(txn); - } - return subscribers; - } - - private List<Contact> getSharedBy(Transaction txn, GroupId g) - throws DbException { - try { - List<Contact> subscribers = new ArrayList<Contact>(); - for (Contact c : db.getContacts(txn)) { - GroupId contactGroup = getContactGroup(c).getId(); - if (listContains(txn, contactGroup, g, SHARED_WITH_US)) - subscribers.add(c); - } - return subscribers; - } catch (IOException e) { - throw new DbException(e); - } - } - @Override public Collection<Contact> getSharedWith(GroupId g) throws DbException { try { @@ -552,6 +524,8 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IS GroupId contactGroup = getContactGroup(c).getId(); if (listContains(txn, contactGroup, g, SHARED_BY_US)) shared.add(c); + else if (listContains(txn, contactGroup, g, SHARED_WITH_US)) + shared.add(c); } db.commitTransaction(txn); } finally { diff --git a/briar-tests/src/org/briarproject/bramble/contact/ContactManagerImplTest.java b/briar-tests/src/org/briarproject/bramble/contact/ContactManagerImplTest.java index 99243107e4f47d912114780564ebe050dc273222..d4f6bfc9762cf70bf1982ae094f2d870f1fd2e4b 100644 --- a/briar-tests/src/org/briarproject/bramble/contact/ContactManagerImplTest.java +++ b/briar-tests/src/org/briarproject/bramble/contact/ContactManagerImplTest.java @@ -1,11 +1,12 @@ package org.briarproject.bramble.contact; -import org.briarproject.BriarTestCase; +import org.briarproject.BriarMockTestCase; 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.crypto.SecretKey; import org.briarproject.bramble.api.db.DatabaseComponent; +import org.briarproject.bramble.api.db.NoSuchContactException; import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.AuthorId; @@ -24,7 +25,7 @@ import static org.briarproject.TestUtils.getSecretKey; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -public class ContactManagerImplTest extends BriarTestCase { +public class ContactManagerImplTest extends BriarMockTestCase { private final Mockery context = new Mockery(); private final DatabaseComponent db = context.mock(DatabaseComponent.class); @@ -66,7 +67,6 @@ public class ContactManagerImplTest extends BriarTestCase { assertEquals(contactId, contactManager .addContact(remote, local, master, timestamp, alice, verified, active)); - context.assertIsSatisfied(); } @Test @@ -82,7 +82,51 @@ public class ContactManagerImplTest extends BriarTestCase { }}); assertEquals(contact, contactManager.getContact(contactId)); - context.assertIsSatisfied(); + } + + @Test + public void testGetContactByAuthor() throws Exception { + final Transaction txn = new Transaction(null, true); + final Collection<Contact> contacts = Collections.singleton(contact); + context.checking(new Expectations() {{ + oneOf(db).startTransaction(true); + will(returnValue(txn)); + oneOf(db).getContactsByAuthorId(txn, remote.getId()); + will(returnValue(contacts)); + oneOf(db).commitTransaction(txn); + oneOf(db).endTransaction(txn); + }}); + + assertEquals(contact, contactManager.getContact(remote.getId(), local)); + } + + @Test(expected = NoSuchContactException.class) + public void testGetContactByUnknownAuthor() throws Exception { + final Transaction txn = new Transaction(null, true); + context.checking(new Expectations() {{ + oneOf(db).startTransaction(true); + will(returnValue(txn)); + oneOf(db).getContactsByAuthorId(txn, remote.getId()); + will(returnValue(Collections.emptyList())); + oneOf(db).endTransaction(txn); + }}); + + contactManager.getContact(remote.getId(), local); + } + + @Test(expected = NoSuchContactException.class) + public void testGetContactByUnknownLocalAuthor() throws Exception { + final Transaction txn = new Transaction(null, true); + final Collection<Contact> contacts = Collections.singleton(contact); + context.checking(new Expectations() {{ + oneOf(db).startTransaction(true); + will(returnValue(txn)); + oneOf(db).getContactsByAuthorId(txn, remote.getId()); + will(returnValue(contacts)); + oneOf(db).endTransaction(txn); + }}); + + contactManager.getContact(remote.getId(), new AuthorId(getRandomId())); } @Test @@ -101,7 +145,6 @@ public class ContactManagerImplTest extends BriarTestCase { }}); assertEquals(activeContacts, contactManager.getActiveContacts()); - context.assertIsSatisfied(); } @Test @@ -118,7 +161,6 @@ public class ContactManagerImplTest extends BriarTestCase { }}); contactManager.removeContact(contactId); - context.assertIsSatisfied(); } @Test @@ -129,7 +171,6 @@ public class ContactManagerImplTest extends BriarTestCase { }}); contactManager.setContactActive(txn, contactId, active); - context.assertIsSatisfied(); } @Test @@ -145,7 +186,6 @@ public class ContactManagerImplTest extends BriarTestCase { }}); assertTrue(contactManager.contactExists(remote.getId(), local)); - context.assertIsSatisfied(); } }