From 562866494b5a600c645a7613e519f13ef50f095a Mon Sep 17 00:00:00 2001 From: Torsten Grote <t@grobox.de> Date: Tue, 6 Dec 2016 10:00:18 -0200 Subject: [PATCH] Add creator and online information to group member list --- .../conversation/GroupActivity.java | 16 +++++++ .../GroupMemberListControllerImpl.java | 11 ++++- .../memberlist/MemberListAdapter.java | 2 + .../memberlist/MemberListItem.java | 44 +++++++++++++------ .../memberlist/MemberListItemHolder.java | 33 ++++++++++++++ .../res/layout/list_item_group_member.xml | 28 +++++++++++- .../briar/api/privategroup/GroupMember.java | 23 +++++++++- .../privategroup/PrivateGroupManagerImpl.java | 26 +++++++++-- 8 files changed, 162 insertions(+), 21 deletions(-) diff --git a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupActivity.java index fb4d4dfede..6cb17a40f2 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupActivity.java @@ -12,6 +12,7 @@ import android.support.v7.widget.LinearLayoutManager; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; +import android.view.View; import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.identity.AuthorId; @@ -72,6 +73,21 @@ public class GroupActivity extends if (groupName != null) setTitle(groupName); loadNamedGroup(); + // Open member list on ActionBar click + View actionBar = findViewById(R.id.action_bar); + if (actionBar != null) { + actionBar.setOnClickListener( + new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent i = new Intent(GroupActivity.this, + GroupMemberListActivity.class); + i.putExtra(GROUP_ID, groupId.getBytes()); + startActivity(i); + } + }); + } + setGroupEnabled(false); } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/GroupMemberListControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/GroupMemberListControllerImpl.java index 4acd6b458e..69bc9ac519 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/GroupMemberListControllerImpl.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/GroupMemberListControllerImpl.java @@ -1,8 +1,10 @@ package org.briarproject.briar.android.privategroup.memberlist; +import org.briarproject.bramble.api.contact.ContactId; import org.briarproject.bramble.api.db.DatabaseExecutor; import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.lifecycle.LifecycleManager; +import org.briarproject.bramble.api.plugin.ConnectionRegistry; import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.briar.android.controller.DbControllerImpl; import org.briarproject.briar.android.controller.handler.ResultExceptionHandler; @@ -24,13 +26,16 @@ class GroupMemberListControllerImpl extends DbControllerImpl private static final Logger LOG = Logger.getLogger(GroupMemberListControllerImpl.class.getName()); + private final ConnectionRegistry connectionRegistry; private final PrivateGroupManager privateGroupManager; @Inject GroupMemberListControllerImpl(@DatabaseExecutor Executor dbExecutor, LifecycleManager lifecycleManager, + ConnectionRegistry connectionRegistry, PrivateGroupManager privateGroupManager) { super(dbExecutor, lifecycleManager); + this.connectionRegistry = connectionRegistry; this.privateGroupManager = privateGroupManager; } @@ -45,7 +50,11 @@ class GroupMemberListControllerImpl extends DbControllerImpl Collection<GroupMember> members = privateGroupManager.getMembers(groupId); for (GroupMember m : members) { - items.add(new MemberListItem(m)); + ContactId c = m.getContactId(); + boolean online = false; + if (c != null) + online = connectionRegistry.isConnected(c); + items.add(new MemberListItem(m, online)); } handler.onResult(items); } catch (DbException e) { diff --git a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/MemberListAdapter.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/MemberListAdapter.java index 5eddb41e3a..0d8910245b 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/MemberListAdapter.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/MemberListAdapter.java @@ -35,7 +35,9 @@ class MemberListAdapter extends @Override public boolean areContentsTheSame(MemberListItem m1, MemberListItem m2) { + if (m1.isOnline() != m2.isOnline()) return false; if (m1.getVisibility() != m2.getVisibility()) return false; + if (m1.getContactId() != m2.getContactId()) return false; if (m1.getStatus() != m2.getStatus()) return false; return true; } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/MemberListItem.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/MemberListItem.java index b055075364..11235ddbeb 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/MemberListItem.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/MemberListItem.java @@ -1,37 +1,55 @@ package org.briarproject.briar.android.privategroup.memberlist; +import android.support.annotation.Nullable; + +import org.briarproject.bramble.api.contact.ContactId; import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author.Status; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.briar.api.privategroup.GroupMember; import org.briarproject.briar.api.privategroup.Visibility; -import javax.annotation.concurrent.Immutable; +import javax.annotation.concurrent.NotThreadSafe; -@Immutable +@NotThreadSafe @NotNullByDefault class MemberListItem { - private final Author member; - private final Status status; - private final Visibility visibility; + private final GroupMember groupMember; + private boolean online; - MemberListItem(GroupMember groupMember) { - this.member = groupMember.getAuthor(); - this.visibility = groupMember.getVisibility(); - this.status = groupMember.getStatus(); + MemberListItem(GroupMember groupMember, boolean online) { + this.groupMember = groupMember; + this.online = online; } Author getMember() { - return member; + return groupMember.getAuthor(); + } + + Status getStatus() { + return groupMember.getStatus(); + } + + boolean isCreator() { + return groupMember.isCreator(); + } + + @Nullable + ContactId getContactId() { + return groupMember.getContactId(); } Visibility getVisibility() { - return visibility; + return groupMember.getVisibility(); } - Status getStatus() { - return status; + boolean isOnline() { + return online; + } + + void setOnline(boolean online) { + this.online = online; } } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/MemberListItemHolder.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/MemberListItemHolder.java index 5b82c5e8b0..725898edc4 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/MemberListItemHolder.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/MemberListItemHolder.java @@ -20,19 +20,52 @@ import static org.briarproject.briar.android.privategroup.VisibilityHelper.getVi class MemberListItemHolder extends RecyclerView.ViewHolder { private final AuthorView author; + private final ImageView bulb; + private final TextView creator; private final ImageView icon; private final TextView info; MemberListItemHolder(View v) { super(v); author = (AuthorView) v.findViewById(R.id.authorView); + bulb = (ImageView) v.findViewById(R.id.bulbView); + creator = (TextView) v.findViewById(R.id.creatorView); icon = (ImageView) v.findViewById(R.id.icon); info = (TextView) v.findViewById(R.id.info); } protected void bind(MemberListItem item) { + // member name, avatar and status author.setAuthor(item.getMember()); author.setAuthorStatus(item.getStatus()); + + // online status of visible contacts + if (item.getContactId() != null) { + bulb.setVisibility(View.VISIBLE); + if (item.isOnline()) { + bulb.setImageResource(R.drawable.contact_connected); + } else { + bulb.setImageResource(R.drawable.contact_disconnected); + } + } else { + bulb.setVisibility(View.GONE); + } + + // text shown for creator + if (item.isCreator()) { + creator.setVisibility(View.VISIBLE); + if (item.getStatus() == OURSELVES) { + creator.setText(R.string.groups_member_created_you); + } else { + creator.setText(creator.getContext() + .getString(R.string.groups_member_created, + item.getMember().getName())); + } + } else { + creator.setVisibility(View.GONE); + } + + // visibility information if (item.getStatus() == OURSELVES || item.getStatus() == UNKNOWN) { icon.setVisibility(View.GONE); info.setVisibility(View.GONE); diff --git a/briar-android/src/main/res/layout/list_item_group_member.xml b/briar-android/src/main/res/layout/list_item_group_member.xml index f02ed68c7d..13591d00f0 100644 --- a/briar-android/src/main/res/layout/list_item_group_member.xml +++ b/briar-android/src/main/res/layout/list_item_group_member.xml @@ -13,17 +13,41 @@ android:id="@+id/authorView" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:layout_marginBottom="@dimen/margin_small" android:layout_marginEnd="@dimen/listitem_horizontal_margin" android:layout_marginRight="@dimen/listitem_horizontal_margin" + android:layout_toLeftOf="@+id/bulbView" app:persona="list"/> <ImageView - android:id="@+id/icon" + android:id="@+id/bulbView" + android:layout_width="16dp" + android:layout_height="16dp" + android:layout_alignBottom="@+id/authorView" + android:layout_alignParentEnd="true" + android:layout_alignParentRight="true" + android:layout_alignTop="@+id/authorView" + android:layout_marginRight="@dimen/listitem_horizontal_margin" + tools:src="@drawable/contact_connected"/> + + <TextView + android:id="@+id/creatorView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/authorView" + android:layout_marginBottom="@dimen/margin_small" + android:layout_marginLeft="@dimen/listitem_group_member_indentation" + android:text="@string/groups_member_created_you" + android:textColor="@color/briar_text_secondary" + tools:visibility="visible"/> + + <ImageView + android:id="@+id/icon" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_below="@+id/creatorView" android:layout_marginLeft="@dimen/listitem_group_member_indentation" android:layout_marginRight="@dimen/margin_small" android:contentDescription="@string/forum_invitation_already_sharing" @@ -33,7 +57,7 @@ android:id="@+id/info" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_below="@+id/authorView" + android:layout_below="@+id/creatorView" android:layout_marginEnd="@dimen/listitem_horizontal_margin" android:layout_marginRight="@dimen/listitem_horizontal_margin" android:layout_toRightOf="@+id/icon" diff --git a/briar-api/src/main/java/org/briarproject/briar/api/privategroup/GroupMember.java b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/GroupMember.java index fca0a05814..b83c1e7b4f 100644 --- a/briar-api/src/main/java/org/briarproject/briar/api/privategroup/GroupMember.java +++ b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/GroupMember.java @@ -1,9 +1,11 @@ package org.briarproject.briar.api.privategroup; +import org.briarproject.bramble.api.contact.ContactId; import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author.Status; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; +import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; @Immutable @@ -12,11 +14,17 @@ public class GroupMember { private final Author author; private final Status status; + private final boolean isCreator; + @Nullable + private final ContactId contactId; private final Visibility visibility; - public GroupMember(Author author, Status status, Visibility visibility) { + public GroupMember(Author author, Status status, boolean isCreator, + @Nullable ContactId contactId, Visibility visibility) { this.author = author; this.status = status; + this.isCreator = isCreator; + this.contactId = contactId; this.visibility = visibility; } @@ -28,6 +36,19 @@ public class GroupMember { return status; } + public boolean isCreator() { + return isCreator; + } + + /** + * Returns the ContactId of a visible contact + * or null if the contact is not visible or the member is no contact. + */ + @Nullable + public ContactId getContactId() { + return contactId; + } + public Visibility getVisibility() { return visibility; } diff --git a/briar-core/src/main/java/org/briarproject/briar/privategroup/PrivateGroupManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/PrivateGroupManagerImpl.java index 91d66bd5a5..1d1d03c887 100644 --- a/briar-core/src/main/java/org/briarproject/briar/privategroup/PrivateGroupManagerImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/PrivateGroupManagerImpl.java @@ -2,6 +2,8 @@ package org.briarproject.briar.privategroup; import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.client.ClientHelper; +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.BdfEntry; import org.briarproject.bramble.api.data.BdfList; @@ -14,6 +16,7 @@ import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author.Status; import org.briarproject.bramble.api.identity.AuthorId; import org.briarproject.bramble.api.identity.IdentityManager; +import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.sync.Group; import org.briarproject.bramble.api.sync.GroupId; @@ -52,6 +55,8 @@ import javax.annotation.concurrent.ThreadSafe; import javax.inject.Inject; import static org.briarproject.bramble.api.identity.Author.Status.OURSELVES; +import static org.briarproject.bramble.api.identity.Author.Status.UNVERIFIED; +import static org.briarproject.bramble.api.identity.Author.Status.VERIFIED; import static org.briarproject.briar.api.privategroup.MessageType.JOIN; import static org.briarproject.briar.api.privategroup.MessageType.POST; import static org.briarproject.briar.api.privategroup.Visibility.INVISIBLE; @@ -79,6 +84,7 @@ class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements PrivateGroupManager { private final PrivateGroupFactory privateGroupFactory; + private final ContactManager contactManager; private final IdentityManager identityManager; private final MessageTracker messageTracker; private final List<PrivateGroupHook> hooks; @@ -87,9 +93,11 @@ class PrivateGroupManagerImpl extends BdfIncomingMessageHook PrivateGroupManagerImpl(ClientHelper clientHelper, MetadataParser metadataParser, DatabaseComponent db, PrivateGroupFactory privateGroupFactory, - IdentityManager identityManager, MessageTracker messageTracker) { + ContactManager contactManager, IdentityManager identityManager, + MessageTracker messageTracker) { super(db, clientHelper, metadataParser); this.privateGroupFactory = privateGroupFactory; + this.contactManager = contactManager; this.identityManager = identityManager; this.messageTracker = messageTracker; hooks = new CopyOnWriteArrayList<PrivateGroupHook>(); @@ -394,10 +402,20 @@ class PrivateGroupManagerImpl extends BdfIncomingMessageHook try { Collection<GroupMember> members = new ArrayList<GroupMember>(); Map<Author, Visibility> authors = getMembers(txn, g); + LocalAuthor la = identityManager.getLocalAuthor(); + PrivateGroup privateGroup = getPrivateGroup(txn, g); for (Entry<Author, Visibility> m : authors.entrySet()) { - Status status = identityManager - .getAuthorStatus(txn, m.getKey().getId()); - members.add(new GroupMember(m.getKey(), status, m.getValue())); + Author a = m.getKey(); + Status status = identityManager.getAuthorStatus(txn, a.getId()); + Visibility v = m.getValue(); + ContactId c = null; + if (v != INVISIBLE && + (status == VERIFIED || status == UNVERIFIED)) { + c = contactManager.getContact(txn, a.getId(), la.getId()) + .getId(); + } + boolean isCreator = privateGroup.getCreator().equals(a); + members.add(new GroupMember(a, status, isCreator, c, v)); } db.commitTransaction(txn); return members; -- GitLab