Merge branch '810-fix-sharing-status-screens' into 'master'

Fix Sharing Status screens

* Remove distinction between "shared with" and "shared by"
* Show all contacts a blog is shared with
* Show online status of contacts in sharing screen

![device-2016-12-05-142949](/uploads/703fbd2d52815374e57edd89f754bf6c/device-2016-12-05-142949.png)

Closes #810

See merge request !445
This commit is contained in:
Torsten Grote
2016-12-07 16:52:29 +00:00
18 changed files with 234 additions and 213 deletions

View File

@@ -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.
*/

View File

@@ -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;

View File

@@ -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));

View File

@@ -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

View File

@@ -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, false);
}
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;
}
}

View File

@@ -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,8 @@ public class ContactItemViewHolder<I extends ContactItem>
layout = (ViewGroup) v;
avatar = (ImageView) v.findViewById(R.id.avatarView);
name = (TextView) v.findViewById(R.id.nameView);
// this can be null as not all layouts that use this ViewHolder have it
bulb = (ImageView) v.findViewById(R.id.bulbView);
}
protected void bind(final I item,
@@ -41,6 +44,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) {

View File

@@ -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;
}

View File

@@ -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));

View File

@@ -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());
}
}

View File

@@ -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());
}
}

View File

@@ -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);
}
});
}

View File

@@ -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>

View File

@@ -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>
<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>

View File

@@ -263,8 +263,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 -->

View File

@@ -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.
*/

View File

@@ -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,

View File

@@ -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 {

View File

@@ -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();
}
}