diff --git a/briar-android/res/layout/list_item_group_join_notice.xml b/briar-android/res/layout/list_item_group_join_notice.xml
new file mode 100644
index 000000000..82796cd56
--- /dev/null
+++ b/briar-android/res/layout/list_item_group_join_notice.xml
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/briar-android/res/layout/list_item_thread.xml b/briar-android/res/layout/list_item_thread.xml
index f788c0ce8..002cc36cf 100644
--- a/briar-android/res/layout/list_item_thread.xml
+++ b/briar-android/res/layout/list_item_thread.xml
@@ -70,16 +70,14 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/margin_medium"
+ android:layout_marginBottom="@dimen/margin_medium"
android:layout_weight="1">
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml
index cc6f0f7d6..cfee02750 100644
--- a/briar-android/res/values/strings.xml
+++ b/briar-android/res/values/strings.xml
@@ -74,6 +74,7 @@
Delete
Accept
Decline
+ Options
Online
Offline
Send
@@ -169,7 +170,10 @@
Message received
Member List
Invite Members
- joined the group.
+ You created the group
+ %s created the group
+ You joined the group
+ %s joined the group
Leave Group
Confirm Leaving Group
Are you sure that you want to leave this group?
diff --git a/briar-android/src/org/briarproject/android/forum/ForumActivity.java b/briar-android/src/org/briarproject/android/forum/ForumActivity.java
index 22c713889..0fe164367 100644
--- a/briar-android/src/org/briarproject/android/forum/ForumActivity.java
+++ b/briar-android/src/org/briarproject/android/forum/ForumActivity.java
@@ -5,6 +5,7 @@ import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.LayoutRes;
+import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.ActivityOptionsCompat;
@@ -26,6 +27,8 @@ import org.briarproject.android.threaded.ThreadListController;
import org.briarproject.api.db.DbException;
import org.briarproject.api.forum.Forum;
import org.briarproject.api.forum.ForumPostHeader;
+import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
import javax.inject.Inject;
@@ -35,8 +38,10 @@ import static android.support.v4.app.ActivityOptionsCompat.makeCustomAnimation;
import static android.widget.Toast.LENGTH_SHORT;
import static org.briarproject.api.forum.ForumConstants.MAX_FORUM_POST_BODY_LENGTH;
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
public class ForumActivity extends
- ThreadListActivity {
+ ThreadListActivity, ForumItem, ForumPostHeader> {
private static final int REQUEST_FORUM_SHARED = 3;
@@ -54,7 +59,7 @@ public class ForumActivity extends
}
@Override
- public void onCreate(Bundle state) {
+ public void onCreate(@Nullable Bundle state) {
super.onCreate(state);
Intent i = getIntent();
diff --git a/briar-android/src/org/briarproject/android/privategroup/VisibilityStringProvider.java b/briar-android/src/org/briarproject/android/privategroup/VisibilityStringProvider.java
new file mode 100644
index 000000000..99ee2fceb
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/privategroup/VisibilityStringProvider.java
@@ -0,0 +1,26 @@
+package org.briarproject.android.privategroup;
+
+import android.support.annotation.StringRes;
+
+import org.briarproject.R;
+import org.briarproject.api.privategroup.Visibility;
+
+public class VisibilityStringProvider {
+
+ @StringRes
+ public static int getVisibilityString(Visibility v) {
+ switch (v) {
+ case VISIBLE:
+ return R.string.groups_reveal_visible;
+ case REVEALED_BY_US:
+ return R.string.groups_reveal_visible_revealed_by_us;
+ case REVEALED_BY_CONTACT:
+ return R.string.groups_reveal_visible_revealed_by_contact;
+ case INVISIBLE:
+ return R.string.groups_reveal_invisible;
+ default:
+ throw new IllegalArgumentException("Unknown visibility");
+ }
+ }
+
+}
diff --git a/briar-android/src/org/briarproject/android/privategroup/conversation/GroupActivity.java b/briar-android/src/org/briarproject/android/privategroup/conversation/GroupActivity.java
index 8a24aaba6..ce1d1c3c2 100644
--- a/briar-android/src/org/briarproject/android/privategroup/conversation/GroupActivity.java
+++ b/briar-android/src/org/briarproject/android/privategroup/conversation/GroupActivity.java
@@ -5,6 +5,7 @@ import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.LayoutRes;
+import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.ActivityOptionsCompat;
@@ -26,10 +27,13 @@ import org.briarproject.android.privategroup.reveal.RevealContactsActivity;
import org.briarproject.android.threaded.ThreadListActivity;
import org.briarproject.android.threaded.ThreadListController;
import org.briarproject.api.db.DbException;
+import org.briarproject.api.identity.AuthorId;
+import org.briarproject.api.identity.LocalAuthor;
import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.api.privategroup.GroupMessageHeader;
import org.briarproject.api.privategroup.PrivateGroup;
+import org.briarproject.api.privategroup.Visibility;
import javax.inject.Inject;
@@ -40,7 +44,7 @@ import static org.briarproject.api.privategroup.PrivateGroupConstants.MAX_GROUP_
@MethodsNotNullByDefault
@ParametersNotNullByDefault
public class GroupActivity extends
- ThreadListActivity
+ ThreadListActivity, GroupMessageItem, GroupMessageHeader>
implements GroupListener, OnClickListener {
private final static int REQUEST_INVITE = 2;
@@ -63,7 +67,7 @@ public class GroupActivity extends
}
@Override
- public void onCreate(Bundle state) {
+ public void onCreate(@Nullable Bundle state) {
super.onCreate(state);
Intent i = getIntent();
@@ -81,9 +85,9 @@ public class GroupActivity extends
}
@Override
- protected GroupMessageAdapter createAdapter(
+ protected GroupMessageAdapter createAdapter(
LinearLayoutManager layoutManager) {
- return new GroupMessageAdapter(this, layoutManager);
+ return new GroupMessageAdapter<>(this, layoutManager);
}
@Override
@@ -105,7 +109,7 @@ public class GroupActivity extends
}
@Override
- protected void onNamedGroupLoaded(PrivateGroup group) {
+ protected void onNamedGroupLoaded(final PrivateGroup group) {
setTitle(group.getName());
// Created by
ActionBar actionBar = getSupportActionBar();
@@ -113,11 +117,12 @@ public class GroupActivity extends
actionBar.setSubtitle(getString(R.string.groups_created_by,
group.getCreator().getName()));
}
- controller.isCreator(group,
- new UiResultExceptionHandler(this) {
+ controller.loadLocalAuthor(
+ new UiResultExceptionHandler(this) {
@Override
- public void onResultUi(Boolean isCreator) {
- GroupActivity.this.isCreator = isCreator;
+ public void onResultUi(LocalAuthor author) {
+ isCreator = group.getCreator().equals(author);
+ adapter.setPerspective(isCreator);
showMenuItems();
}
@@ -272,6 +277,11 @@ public class GroupActivity extends
});
}
+ @Override
+ public void onContactRelationshipRevealed(AuthorId memberId, Visibility v) {
+ adapter.updateVisibility(memberId, v);
+ }
+
@Override
public void onGroupDissolved() {
setGroupEnabled(false);
diff --git a/briar-android/src/org/briarproject/android/privategroup/conversation/GroupController.java b/briar-android/src/org/briarproject/android/privategroup/conversation/GroupController.java
index 18915ab15..523abc1b9 100644
--- a/briar-android/src/org/briarproject/android/privategroup/conversation/GroupController.java
+++ b/briar-android/src/org/briarproject/android/privategroup/conversation/GroupController.java
@@ -5,20 +5,26 @@ import android.support.annotation.UiThread;
import org.briarproject.android.controller.handler.ResultExceptionHandler;
import org.briarproject.android.threaded.ThreadListController;
import org.briarproject.api.db.DbException;
+import org.briarproject.api.identity.AuthorId;
+import org.briarproject.api.identity.LocalAuthor;
import org.briarproject.api.privategroup.GroupMessageHeader;
import org.briarproject.api.privategroup.PrivateGroup;
+import org.briarproject.api.privategroup.Visibility;
public interface GroupController
extends
ThreadListController {
- void isCreator(PrivateGroup group,
- ResultExceptionHandler handler);
+ void loadLocalAuthor(
+ ResultExceptionHandler handler);
void isDissolved(
ResultExceptionHandler handler);
interface GroupListener extends ThreadListListener {
+ @UiThread
+ void onContactRelationshipRevealed(AuthorId memberId, Visibility v);
+
@UiThread
void onGroupDissolved();
}
diff --git a/briar-android/src/org/briarproject/android/privategroup/conversation/GroupControllerImpl.java b/briar-android/src/org/briarproject/android/privategroup/conversation/GroupControllerImpl.java
index e0ba5d3d8..639115940 100644
--- a/briar-android/src/org/briarproject/android/privategroup/conversation/GroupControllerImpl.java
+++ b/briar-android/src/org/briarproject/android/privategroup/conversation/GroupControllerImpl.java
@@ -16,6 +16,7 @@ import org.briarproject.api.event.GroupMessageAddedEvent;
import org.briarproject.api.identity.IdentityManager;
import org.briarproject.api.identity.LocalAuthor;
import org.briarproject.api.lifecycle.LifecycleManager;
+import org.briarproject.api.privategroup.ContactRelationshipRevealedEvent;
import org.briarproject.api.privategroup.GroupMessage;
import org.briarproject.api.privategroup.GroupMessageFactory;
import org.briarproject.api.privategroup.GroupMessageHeader;
@@ -32,7 +33,6 @@ import java.util.logging.Logger;
import javax.inject.Inject;
import static java.lang.Math.max;
-
import static java.util.logging.Level.WARNING;
public class GroupControllerImpl extends
@@ -80,6 +80,18 @@ public class GroupControllerImpl extends
}
});
}
+ } else if (e instanceof ContactRelationshipRevealedEvent) {
+ final ContactRelationshipRevealedEvent c =
+ (ContactRelationshipRevealedEvent) e;
+ if (getGroupId().equals(c.getGroupId())) {
+ listener.runOnUiThreadUnlessDestroyed(new Runnable() {
+ @Override
+ public void run() {
+ listener.onContactRelationshipRevealed(c.getMemberId(),
+ c.getVisibility());
+ }
+ });
+ }
} else if (e instanceof GroupDissolvedEvent) {
GroupDissolvedEvent g = (GroupDissolvedEvent) e;
if (getGroupId().equals(g.getGroupId())) {
@@ -182,22 +194,20 @@ public class GroupControllerImpl extends
protected GroupMessageItem buildItem(GroupMessageHeader header,
String body) {
if (header instanceof JoinMessageHeader) {
- return new JoinMessageItem(header, body);
+ return new JoinMessageItem((JoinMessageHeader) header, body);
}
return new GroupMessageItem(header, body);
}
@Override
- public void isCreator(final PrivateGroup group,
- final ResultExceptionHandler handler) {
+ public void loadLocalAuthor(
+ final ResultExceptionHandler handler) {
runOnDbThread(new Runnable() {
@Override
public void run() {
try {
LocalAuthor author = identityManager.getLocalAuthor();
- boolean isCreator =
- author.getId().equals(group.getCreator().getId());
- handler.onResult(isCreator);
+ handler.onResult(author);
} catch (DbException e) {
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
diff --git a/briar-android/src/org/briarproject/android/privategroup/conversation/GroupMessageAdapter.java b/briar-android/src/org/briarproject/android/privategroup/conversation/GroupMessageAdapter.java
index c042a1829..3400c9315 100644
--- a/briar-android/src/org/briarproject/android/privategroup/conversation/GroupMessageAdapter.java
+++ b/briar-android/src/org/briarproject/android/privategroup/conversation/GroupMessageAdapter.java
@@ -11,11 +11,20 @@ import org.briarproject.R;
import org.briarproject.android.threaded.BaseThreadItemViewHolder;
import org.briarproject.android.threaded.ThreadItemAdapter;
import org.briarproject.android.threaded.ThreadPostViewHolder;
+import org.briarproject.api.identity.AuthorId;
+import org.briarproject.api.nullsafety.NotNullByDefault;
+import org.briarproject.api.privategroup.Visibility;
+
+import static android.support.v7.widget.RecyclerView.NO_POSITION;
@UiThread
-public class GroupMessageAdapter extends ThreadItemAdapter {
+@NotNullByDefault
+public class GroupMessageAdapter
+ extends ThreadItemAdapter {
- public GroupMessageAdapter(ThreadItemListener listener,
+ private boolean isCreator = false;
+
+ public GroupMessageAdapter(ThreadItemListener listener,
LinearLayoutManager layoutManager) {
super(listener, layoutManager);
}
@@ -29,14 +38,41 @@ public class GroupMessageAdapter extends ThreadItemAdapter {
}
@Override
- public BaseThreadItemViewHolder onCreateViewHolder(
+ public BaseThreadItemViewHolder onCreateViewHolder(
ViewGroup parent, int type) {
View v = LayoutInflater.from(parent.getContext())
.inflate(type, parent, false);
- if (type == R.layout.list_item_thread_notice) {
- return new JoinMessageItemViewHolder(v);
+ if (type == R.layout.list_item_group_join_notice) {
+ return (BaseThreadItemViewHolder)
+ new JoinMessageItemViewHolder(v, isCreator);
}
return new ThreadPostViewHolder<>(v);
}
+ void setPerspective(boolean isCreator) {
+ this.isCreator = isCreator;
+ notifyDataSetChanged();
+ }
+
+ void updateVisibility(AuthorId memberId, Visibility v) {
+ int position = findItemPosition(memberId);
+ if (position != NO_POSITION) {
+ GroupMessageItem item = items.get(position);
+ if (item instanceof JoinMessageItem) {
+ ((JoinMessageItem) item).setVisibility(v);
+ notifyItemChanged(position, item);
+ }
+ }
+ }
+
+ private int findItemPosition(AuthorId a) {
+ int count = items.size();
+ for (int i = 0; i < count; i++) {
+ I item = items.get(i);
+ if (item.getAuthor().getId().equals(a))
+ return i;
+ }
+ return NO_POSITION; // Not found
+ }
+
}
diff --git a/briar-android/src/org/briarproject/android/privategroup/conversation/GroupMessageItem.java b/briar-android/src/org/briarproject/android/privategroup/conversation/GroupMessageItem.java
index 9deb0424e..47104e882 100644
--- a/briar-android/src/org/briarproject/android/privategroup/conversation/GroupMessageItem.java
+++ b/briar-android/src/org/briarproject/android/privategroup/conversation/GroupMessageItem.java
@@ -8,6 +8,7 @@ import org.briarproject.android.threaded.ThreadItem;
import org.briarproject.api.identity.Author;
import org.briarproject.api.identity.Author.Status;
import org.briarproject.api.privategroup.GroupMessageHeader;
+import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.MessageId;
import javax.annotation.concurrent.NotThreadSafe;
@@ -16,15 +17,23 @@ import javax.annotation.concurrent.NotThreadSafe;
@NotThreadSafe
class GroupMessageItem extends ThreadItem {
- private GroupMessageItem(MessageId messageId, MessageId parentId,
+ private final GroupId groupId;
+
+ private GroupMessageItem(MessageId messageId, GroupId groupId,
+ MessageId parentId,
String text, long timestamp, Author author, Status status,
boolean isRead) {
super(messageId, parentId, text, timestamp, author, status, isRead);
+ this.groupId = groupId;
}
GroupMessageItem(GroupMessageHeader h, String text) {
- this(h.getId(), h.getParentId(), text, h.getTimestamp(), h.getAuthor(),
- h.getAuthorStatus(), h.isRead());
+ this(h.getId(), h.getGroupId(), h.getParentId(), text, h.getTimestamp(),
+ h.getAuthor(), h.getAuthorStatus(), h.isRead());
+ }
+
+ public GroupId getGroupId() {
+ return groupId;
}
@LayoutRes
diff --git a/briar-android/src/org/briarproject/android/privategroup/conversation/JoinMessageItem.java b/briar-android/src/org/briarproject/android/privategroup/conversation/JoinMessageItem.java
index 44c732ffd..4e5bf7030 100644
--- a/briar-android/src/org/briarproject/android/privategroup/conversation/JoinMessageItem.java
+++ b/briar-android/src/org/briarproject/android/privategroup/conversation/JoinMessageItem.java
@@ -4,7 +4,8 @@ import android.support.annotation.LayoutRes;
import android.support.annotation.UiThread;
import org.briarproject.R;
-import org.briarproject.api.privategroup.GroupMessageHeader;
+import org.briarproject.api.privategroup.JoinMessageHeader;
+import org.briarproject.api.privategroup.Visibility;
import javax.annotation.concurrent.NotThreadSafe;
@@ -12,9 +13,14 @@ import javax.annotation.concurrent.NotThreadSafe;
@NotThreadSafe
class JoinMessageItem extends GroupMessageItem {
- JoinMessageItem(GroupMessageHeader h,
+ private Visibility visibility;
+ private final boolean isInitial;
+
+ JoinMessageItem(JoinMessageHeader h,
String text) {
super(h, text);
+ this.visibility = h.getVisibility();
+ this.isInitial = h.isInitial();
}
@Override
@@ -29,7 +35,19 @@ class JoinMessageItem extends GroupMessageItem {
@LayoutRes
public int getLayout() {
- return R.layout.list_item_thread_notice;
+ return R.layout.list_item_group_join_notice;
+ }
+
+ public Visibility getVisibility() {
+ return visibility;
+ }
+
+ public void setVisibility(Visibility visibility) {
+ this.visibility = visibility;
+ }
+
+ public boolean isInitial() {
+ return isInitial;
}
}
diff --git a/briar-android/src/org/briarproject/android/privategroup/conversation/JoinMessageItemViewHolder.java b/briar-android/src/org/briarproject/android/privategroup/conversation/JoinMessageItemViewHolder.java
index 972a6149e..a71103be7 100644
--- a/briar-android/src/org/briarproject/android/privategroup/conversation/JoinMessageItemViewHolder.java
+++ b/briar-android/src/org/briarproject/android/privategroup/conversation/JoinMessageItemViewHolder.java
@@ -1,30 +1,110 @@
package org.briarproject.android.privategroup.conversation;
+import android.content.Context;
+import android.content.Intent;
import android.support.annotation.UiThread;
import android.view.View;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.TextView;
import org.briarproject.R;
+import org.briarproject.android.privategroup.reveal.RevealContactsActivity;
import org.briarproject.android.threaded.BaseThreadItemViewHolder;
import org.briarproject.android.threaded.ThreadItemAdapter;
import org.briarproject.android.threaded.ThreadItemAdapter.ThreadItemListener;
import org.briarproject.api.nullsafety.NotNullByDefault;
+import static org.briarproject.android.BriarActivity.GROUP_ID;
+import static org.briarproject.android.privategroup.VisibilityStringProvider.getVisibilityString;
+import static org.briarproject.api.identity.Author.Status.OURSELVES;
+import static org.briarproject.api.identity.Author.Status.UNKNOWN;
+import static org.briarproject.api.privategroup.Visibility.INVISIBLE;
+
@UiThread
@NotNullByDefault
public class JoinMessageItemViewHolder
- extends BaseThreadItemViewHolder {
+ extends BaseThreadItemViewHolder {
- public JoinMessageItemViewHolder(View v) {
+ private final boolean isCreator;
+ private final ImageView icon;
+ private final TextView info;
+ private final Button options;
+
+ public JoinMessageItemViewHolder(View v, boolean isCreator) {
super(v);
+ this.isCreator = isCreator;
+ icon = (ImageView) v.findViewById(R.id.icon);
+ info = (TextView) v.findViewById(R.id.info);
+ options = (Button) v.findViewById(R.id.optionsButton);
}
@Override
- public void bind(final ThreadItemAdapter adapter,
- final ThreadItemListener listener,
- final GroupMessageItem item, int pos) {
+ public void bind(ThreadItemAdapter adapter,
+ ThreadItemListener listener, JoinMessageItem item,
+ int pos) {
super.bind(adapter, listener, item, pos);
- textView.setText(getContext().getString(R.string.groups_member_joined));
+ if (isCreator) bindForCreator(item);
+ else bind(item);
+ }
+
+ private void bindForCreator(final JoinMessageItem item) {
+ if (item.isInitial()) {
+ textView.setText(
+ getContext().getString(R.string.groups_member_created_you));
+ } else {
+ textView.setText(
+ getContext().getString(R.string.groups_member_joined,
+ item.getAuthor().getName()));
+ }
+ icon.setVisibility(View.GONE);
+ info.setVisibility(View.GONE);
+ options.setVisibility(View.GONE);
+ }
+
+ private void bind(final JoinMessageItem item) {
+ final Context ctx = getContext();
+
+ if (item.isInitial()) {
+ textView.setText(ctx.getString(R.string.groups_member_created,
+ item.getAuthor().getName()));
+ } else {
+ if (item.getStatus() == OURSELVES) {
+ textView.setText(
+ ctx.getString(R.string.groups_member_joined_you));
+ } else {
+ textView.setText(ctx.getString(R.string.groups_member_joined,
+ item.getAuthor().getName()));
+ }
+ }
+
+ if (item.getStatus() == OURSELVES || item.getStatus() == UNKNOWN) {
+ icon.setVisibility(View.GONE);
+ info.setVisibility(View.GONE);
+ options.setVisibility(View.GONE);
+ } else {
+ icon.setVisibility(View.VISIBLE);
+ info.setVisibility(View.VISIBLE);
+ info.setText(getVisibilityString(item.getVisibility()));
+
+ if (item.getVisibility() == INVISIBLE) {
+ icon.setImageResource(R.drawable.ic_visibility_off);
+ options.setVisibility(View.VISIBLE);
+ options.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Intent i =
+ new Intent(ctx, RevealContactsActivity.class);
+ i.putExtra(GROUP_ID, item.getGroupId().getBytes());
+ ctx.startActivity(i);
+ }
+ });
+ } else {
+ icon.setImageResource(R.drawable.ic_visibility);
+ options.setVisibility(View.GONE);
+ }
+ }
}
}
diff --git a/briar-android/src/org/briarproject/android/privategroup/reveal/RevealableContactViewHolder.java b/briar-android/src/org/briarproject/android/privategroup/reveal/RevealableContactViewHolder.java
index f2131482c..7da31e7f0 100644
--- a/briar-android/src/org/briarproject/android/privategroup/reveal/RevealableContactViewHolder.java
+++ b/briar-android/src/org/briarproject/android/privategroup/reveal/RevealableContactViewHolder.java
@@ -10,6 +10,7 @@ import org.briarproject.android.contactselection.BaseSelectableContactHolder;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.jetbrains.annotations.Nullable;
+import static org.briarproject.android.privategroup.VisibilityStringProvider.getVisibilityString;
import static org.briarproject.android.util.AndroidUtils.GREY_OUT;
import static org.briarproject.api.privategroup.Visibility.INVISIBLE;
@@ -31,21 +32,7 @@ public class RevealableContactViewHolder
OnContactClickListener listener) {
super.bind(item, listener);
- switch (item.getVisibility()) {
- case VISIBLE:
- info.setText(R.string.groups_reveal_visible);
- break;
- case REVEALED_BY_US:
- info.setText(R.string.groups_reveal_visible_revealed_by_us);
- break;
- case REVEALED_BY_CONTACT:
- info.setText(
- R.string.groups_reveal_visible_revealed_by_contact);
- break;
- case INVISIBLE:
- info.setText(R.string.groups_reveal_invisible);
- break;
- }
+ info.setText(getVisibilityString(item.getVisibility()));
if (item.getVisibility() == INVISIBLE) {
icon.setImageResource(R.drawable.ic_visibility_off);
diff --git a/briar-android/src/org/briarproject/android/threaded/ThreadItemAdapter.java b/briar-android/src/org/briarproject/android/threaded/ThreadItemAdapter.java
index 7c3ee9079..546b97372 100644
--- a/briar-android/src/org/briarproject/android/threaded/ThreadItemAdapter.java
+++ b/briar-android/src/org/briarproject/android/threaded/ThreadItemAdapter.java
@@ -27,7 +27,7 @@ public class ThreadItemAdapter
static final int UNDEFINED = -1;
- private final NestedTreeList items = new NestedTreeList<>();
+ protected final NestedTreeList items = new NestedTreeList<>();
private final Map animatingItems = new HashMap<>();
private final ThreadItemListener listener;
private final LinearLayoutManager layoutManager;
@@ -61,6 +61,11 @@ public class ThreadItemAdapter
ui.bind(this, listener, item, position);
}
+ /**
+ * Contrary to the super class adapter,
+ * this returns the number of visible items,
+ * not all items in the dataset.
+ */
@Override
public int getItemCount() {
return getVisiblePos(null);
diff --git a/briar-android/src/org/briarproject/android/threaded/ThreadListActivity.java b/briar-android/src/org/briarproject/android/threaded/ThreadListActivity.java
index e4bd39e2a..ed2ebdfa9 100644
--- a/briar-android/src/org/briarproject/android/threaded/ThreadListActivity.java
+++ b/briar-android/src/org/briarproject/android/threaded/ThreadListActivity.java
@@ -24,6 +24,8 @@ import org.briarproject.android.view.TextInputView.TextInputListener;
import org.briarproject.api.clients.NamedGroup;
import org.briarproject.api.clients.PostHeader;
import org.briarproject.api.db.DbException;
+import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.MessageId;
import org.briarproject.util.StringUtils;
@@ -35,7 +37,9 @@ import static android.support.design.widget.Snackbar.make;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
-public abstract class ThreadListActivity
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
+public abstract class ThreadListActivity, I extends ThreadItem, H extends PostHeader>
extends BriarActivity
implements ThreadListListener, TextInputListener,
ThreadItemListener {
@@ -46,7 +50,7 @@ public abstract class ThreadListActivity adapter;
+ protected A adapter;
protected BriarRecyclerView list;
protected TextInputView textInput;
protected GroupId groupId;
@@ -57,7 +61,7 @@ public abstract class ThreadListActivity createAdapter(
- LinearLayoutManager layoutManager);
+ protected abstract A createAdapter(LinearLayoutManager layoutManager);
protected void loadNamedGroup() {
getController().loadNamedGroup(
diff --git a/briar-api/src/org/briarproject/api/privategroup/ContactRelationshipRevealedEvent.java b/briar-api/src/org/briarproject/api/privategroup/ContactRelationshipRevealedEvent.java
index 40de39d1e..2fd120315 100644
--- a/briar-api/src/org/briarproject/api/privategroup/ContactRelationshipRevealedEvent.java
+++ b/briar-api/src/org/briarproject/api/privategroup/ContactRelationshipRevealedEvent.java
@@ -1,6 +1,7 @@
package org.briarproject.api.privategroup;
import org.briarproject.api.event.Event;
+import org.briarproject.api.identity.AuthorId;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.GroupId;
@@ -11,11 +12,13 @@ import javax.annotation.concurrent.Immutable;
public class ContactRelationshipRevealedEvent extends Event {
private final GroupId groupId;
+ private final AuthorId memberId;
private final Visibility visibility;
- public ContactRelationshipRevealedEvent(GroupId groupId,
+ public ContactRelationshipRevealedEvent(GroupId groupId, AuthorId memberId,
Visibility visibility) {
this.groupId = groupId;
+ this.memberId = memberId;
this.visibility = visibility;
}
@@ -23,6 +26,10 @@ public class ContactRelationshipRevealedEvent extends Event {
return groupId;
}
+ public AuthorId getMemberId() {
+ return memberId;
+ }
+
public Visibility getVisibility() {
return visibility;
}
diff --git a/briar-api/src/org/briarproject/api/privategroup/JoinMessageHeader.java b/briar-api/src/org/briarproject/api/privategroup/JoinMessageHeader.java
index 8b14717a6..92beb6a68 100644
--- a/briar-api/src/org/briarproject/api/privategroup/JoinMessageHeader.java
+++ b/briar-api/src/org/briarproject/api/privategroup/JoinMessageHeader.java
@@ -9,15 +9,21 @@ import javax.annotation.concurrent.Immutable;
public class JoinMessageHeader extends GroupMessageHeader {
private final Visibility visibility;
+ private final boolean isCreator;
- public JoinMessageHeader(GroupMessageHeader h, Visibility visibility) {
+ public JoinMessageHeader(GroupMessageHeader h, Visibility visibility, boolean isCreator) {
super(h.getGroupId(), h.getId(), h.getParentId(), h.getTimestamp(),
h.getAuthor(), h.getAuthorStatus(), h.isRead());
this.visibility = visibility;
+ this.isCreator = isCreator;
}
public Visibility getVisibility() {
return visibility;
}
+ public boolean isInitial() {
+ return isCreator;
+ }
+
}
diff --git a/briar-core/src/org/briarproject/privategroup/GroupConstants.java b/briar-core/src/org/briarproject/privategroup/GroupConstants.java
index 72f57748c..b1e203aa7 100644
--- a/briar-core/src/org/briarproject/privategroup/GroupConstants.java
+++ b/briar-core/src/org/briarproject/privategroup/GroupConstants.java
@@ -13,6 +13,7 @@ interface GroupConstants {
String KEY_MEMBER_ID = "memberId";
String KEY_MEMBER_NAME = "memberName";
String KEY_MEMBER_PUBLIC_KEY = "memberPublicKey";
+ String KEY_INITIAL_JOIN_MSG = "initialJoinMsg";
String GROUP_KEY_MEMBERS = "members";
String GROUP_KEY_OUR_GROUP = "ourGroup";
diff --git a/briar-core/src/org/briarproject/privategroup/GroupMessageValidator.java b/briar-core/src/org/briarproject/privategroup/GroupMessageValidator.java
index 54b6324fc..13ab704aa 100644
--- a/briar-core/src/org/briarproject/privategroup/GroupMessageValidator.java
+++ b/briar-core/src/org/briarproject/privategroup/GroupMessageValidator.java
@@ -29,6 +29,7 @@ import static org.briarproject.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH
import static org.briarproject.api.privategroup.MessageType.JOIN;
import static org.briarproject.api.privategroup.MessageType.POST;
import static org.briarproject.api.privategroup.PrivateGroupConstants.MAX_GROUP_POST_BODY_LENGTH;
+import static org.briarproject.privategroup.GroupConstants.KEY_INITIAL_JOIN_MSG;
import static org.briarproject.privategroup.GroupConstants.KEY_MEMBER_ID;
import static org.briarproject.privategroup.GroupConstants.KEY_MEMBER_NAME;
import static org.briarproject.privategroup.GroupConstants.KEY_MEMBER_PUBLIC_KEY;
@@ -99,10 +100,12 @@ class GroupMessageValidator extends BdfMessageValidator {
// invite is null if the member is the creator of the private group
Author creator = pg.getCreator();
+ boolean isCreator = false;
BdfList invite = body.getOptionalList(3);
if (invite == null) {
if (!member.equals(creator))
throw new InvalidMessageException();
+ isCreator = true;
} else {
if (member.equals(creator))
throw new InvalidMessageException();
@@ -149,6 +152,7 @@ class GroupMessageValidator extends BdfMessageValidator {
// Return the metadata and no dependencies
BdfDictionary meta = new BdfDictionary();
+ meta.put(KEY_INITIAL_JOIN_MSG, isCreator);
return new BdfMessageContext(meta);
}
diff --git a/briar-core/src/org/briarproject/privategroup/PrivateGroupManagerImpl.java b/briar-core/src/org/briarproject/privategroup/PrivateGroupManagerImpl.java
index 5ff1193f9..c90312b0a 100644
--- a/briar-core/src/org/briarproject/privategroup/PrivateGroupManagerImpl.java
+++ b/briar-core/src/org/briarproject/privategroup/PrivateGroupManagerImpl.java
@@ -60,6 +60,7 @@ import static org.briarproject.privategroup.GroupConstants.GROUP_KEY_DISSOLVED;
import static org.briarproject.privategroup.GroupConstants.GROUP_KEY_MEMBERS;
import static org.briarproject.privategroup.GroupConstants.GROUP_KEY_OUR_GROUP;
import static org.briarproject.privategroup.GroupConstants.GROUP_KEY_VISIBILITY;
+import static org.briarproject.privategroup.GroupConstants.KEY_INITIAL_JOIN_MSG;
import static org.briarproject.privategroup.GroupConstants.KEY_MEMBER_ID;
import static org.briarproject.privategroup.GroupConstants.KEY_MEMBER_NAME;
import static org.briarproject.privategroup.GroupConstants.KEY_MEMBER_PUBLIC_KEY;
@@ -114,16 +115,17 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
new BdfEntry(GROUP_KEY_DISSOLVED, false)
);
clientHelper.mergeGroupMetadata(txn, group.getId(), meta);
- joinPrivateGroup(txn, joinMsg);
+ joinPrivateGroup(txn, joinMsg, creator);
} catch (FormatException e) {
throw new DbException(e);
}
}
- private void joinPrivateGroup(Transaction txn, GroupMessage m)
- throws DbException, FormatException {
+ private void joinPrivateGroup(Transaction txn, GroupMessage m,
+ boolean creator) throws DbException, FormatException {
BdfDictionary meta = new BdfDictionary();
meta.put(KEY_TYPE, JOIN.getInt());
+ meta.put(KEY_INITIAL_JOIN_MSG, creator);
addMessageMetadata(meta, m, true);
clientHelper.addLocalMessage(txn, m.getMessage(), meta, true);
trackOutgoingMessage(txn, m.getMessage());
@@ -387,7 +389,8 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
GroupMessageHeader header =
getGroupMessageHeader(txn, g, id, meta, statuses);
- return new JoinMessageHeader(header, v);
+ boolean creator = meta.getBoolean(KEY_INITIAL_JOIN_MSG);
+ return new JoinMessageHeader(header, v, creator);
}
@Override
@@ -461,7 +464,7 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
if (!foundMember) throw new ProtocolStateException();
if (changed) {
clientHelper.mergeGroupMetadata(txn, g, meta);
- txn.attach(new ContactRelationshipRevealedEvent(g, v));
+ txn.attach(new ContactRelationshipRevealedEvent(g, a, v));
}
}