mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 10:49:06 +01:00
Merge branch '41-alias-frontend-base' into 'master'
[android] Show contact aliases in UI See merge request briar/briar!971
This commit is contained in:
@@ -96,6 +96,12 @@ public interface ContactManager {
|
||||
void setContactActive(Transaction txn, ContactId c, boolean active)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Sets an alias name for the contact or unsets it if alias is null.
|
||||
*/
|
||||
void setContactAlias(Transaction txn, ContactId c, @Nullable String alias)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Sets an alias name for the contact or unsets it if alias is null.
|
||||
*/
|
||||
|
||||
@@ -10,7 +10,11 @@ import javax.annotation.concurrent.Immutable;
|
||||
public class AuthorInfo {
|
||||
|
||||
public enum Status {
|
||||
NONE, ANONYMOUS, UNKNOWN, UNVERIFIED, VERIFIED, OURSELVES
|
||||
NONE, ANONYMOUS, UNKNOWN, UNVERIFIED, VERIFIED, OURSELVES;
|
||||
|
||||
public boolean isContact() {
|
||||
return this == UNVERIFIED || this == VERIFIED;
|
||||
}
|
||||
}
|
||||
|
||||
private final Status status;
|
||||
|
||||
@@ -163,14 +163,20 @@ class ContactManagerImpl implements ContactManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContactAlias(ContactId c, @Nullable String alias)
|
||||
throws DbException {
|
||||
public void setContactAlias(Transaction txn, ContactId c,
|
||||
@Nullable String alias) throws DbException {
|
||||
if (alias != null) {
|
||||
int aliasLength = toUtf8(alias).length;
|
||||
if (aliasLength == 0 || aliasLength > MAX_AUTHOR_NAME_LENGTH)
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
db.transaction(false, txn -> db.setContactAlias(txn, c, alias));
|
||||
db.setContactAlias(txn, c, alias);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContactAlias(ContactId c, @Nullable String alias)
|
||||
throws DbException {
|
||||
db.transaction(false, txn -> setContactAlias(txn, c, alias));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -204,7 +204,8 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testSetContactAliasTooLong() throws Exception {
|
||||
contactManager.setContactAlias(contactId,
|
||||
Transaction txn = new Transaction(null, false);
|
||||
contactManager.setContactAlias(txn, contactId,
|
||||
getRandomString(MAX_AUTHOR_NAME_LENGTH + 1));
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ import android.view.ViewGroup;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.briarproject.bramble.api.identity.Author;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.view.AuthorView;
|
||||
@@ -98,9 +97,7 @@ class BlogPostViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
// author and date
|
||||
BlogPostHeader post = item.getPostHeader();
|
||||
Author a = post.getAuthor();
|
||||
author.setAuthor(a);
|
||||
author.setAuthorInfo(post.getAuthorInfo());
|
||||
author.setAuthor(post.getAuthor(), post.getAuthorInfo());
|
||||
author.setDate(post.getTimestamp());
|
||||
author.setPersona(
|
||||
item.isRssFeed() ? AuthorView.RSS_FEED : AuthorView.NORMAL);
|
||||
@@ -143,8 +140,7 @@ class BlogPostViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
private void onBindComment(BlogCommentItem item) {
|
||||
// reblogger
|
||||
reblogger.setAuthor(item.getAuthor());
|
||||
reblogger.setAuthorInfo(item.getAuthorInfo());
|
||||
reblogger.setAuthor(item.getAuthor(), item.getAuthorInfo());
|
||||
reblogger.setDate(item.getTimestamp());
|
||||
if (!fullText) {
|
||||
reblogger.setAuthorClickable(v -> listener.onAuthorClick(item));
|
||||
@@ -165,8 +161,7 @@ class BlogPostViewHolder extends RecyclerView.ViewHolder {
|
||||
AuthorView author = v.findViewById(R.id.authorView);
|
||||
TextView text = v.findViewById(R.id.textView);
|
||||
|
||||
author.setAuthor(c.getAuthor());
|
||||
author.setAuthorInfo(c.getAuthorInfo());
|
||||
author.setAuthor(c.getAuthor(), c.getAuthorInfo());
|
||||
author.setDate(c.getTimestamp());
|
||||
// TODO make author clickable #624
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.briarproject.briar.android.contact;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.view.View;
|
||||
|
||||
import org.briarproject.bramble.api.contact.ContactId;
|
||||
@@ -9,6 +10,7 @@ import org.briarproject.briar.android.util.BriarAdapter;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static android.support.v7.util.SortedList.INVALID_POSITION;
|
||||
import static org.briarproject.briar.android.util.UiUtils.getContactDisplayName;
|
||||
|
||||
public abstract class BaseContactListAdapter<I extends ContactItem, VH extends ContactItemViewHolder<I>>
|
||||
extends BriarAdapter<I, VH> {
|
||||
@@ -23,15 +25,15 @@ public abstract class BaseContactListAdapter<I extends ContactItem, VH extends C
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(VH ui, int position) {
|
||||
public void onBindViewHolder(@NonNull VH ui, int position) {
|
||||
I item = items.get(position);
|
||||
ui.bind(item, listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compare(I c1, I c2) {
|
||||
return c1.getContact().getAuthor().getName()
|
||||
.compareTo(c2.getContact().getAuthor().getName());
|
||||
return getContactDisplayName(c1.getContact())
|
||||
.compareTo(getContactDisplayName(c2.getContact()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -16,6 +16,8 @@ import javax.annotation.Nullable;
|
||||
|
||||
import im.delight.android.identicons.IdenticonDrawable;
|
||||
|
||||
import static org.briarproject.briar.android.util.UiUtils.getContactDisplayName;
|
||||
|
||||
@UiThread
|
||||
@NotNullByDefault
|
||||
public class ContactItemViewHolder<I extends ContactItem>
|
||||
@@ -41,8 +43,7 @@ public class ContactItemViewHolder<I extends ContactItem>
|
||||
Author author = item.getContact().getAuthor();
|
||||
avatar.setImageDrawable(
|
||||
new IdenticonDrawable(author.getId().getBytes()));
|
||||
String contactName = author.getName();
|
||||
name.setText(contactName);
|
||||
name.setText(getContactDisplayName(item.getContact()));
|
||||
|
||||
if (bulb != null) {
|
||||
// online/offline
|
||||
|
||||
@@ -24,6 +24,7 @@ import static org.briarproject.briar.android.contact.ConversationRequestItem.Req
|
||||
import static org.briarproject.briar.android.contact.ConversationRequestItem.RequestType.FORUM;
|
||||
import static org.briarproject.briar.android.contact.ConversationRequestItem.RequestType.GROUP;
|
||||
import static org.briarproject.briar.android.contact.ConversationRequestItem.RequestType.INTRODUCTION;
|
||||
import static org.briarproject.briar.android.util.UiUtils.getContactDisplayName;
|
||||
|
||||
@UiThread
|
||||
@NotNullByDefault
|
||||
@@ -188,33 +189,36 @@ class ConversationVisitor implements PrivateMessageVisitor<ConversationItem> {
|
||||
|
||||
@Override
|
||||
public ConversationItem visitIntroductionRequest(IntroductionRequest r) {
|
||||
String name = getContactDisplayName(r.getNameable(), r.getAlias());
|
||||
if (r.isLocal()) {
|
||||
String text = ctx.getString(R.string.introduction_request_sent,
|
||||
contactName.getValue(), r.getName());
|
||||
contactName.getValue(), name);
|
||||
return new ConversationNoticeOutItem(text, r);
|
||||
} else {
|
||||
String text = ctx.getString(R.string.introduction_request_received,
|
||||
contactName.getValue(), r.getName());
|
||||
contactName.getValue(), name);
|
||||
return new ConversationRequestItem(text, INTRODUCTION, r);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConversationItem visitIntroductionResponse(IntroductionResponse r) {
|
||||
String introducedAuthor =
|
||||
getContactDisplayName(r.getIntroducedAuthor(),
|
||||
r.getIntroducedAuthorInfo().getAlias());
|
||||
if (r.isLocal()) {
|
||||
String text;
|
||||
if (r.wasAccepted()) {
|
||||
String introducee = r.getIntroducedAuthor().getName();
|
||||
text = ctx.getString(
|
||||
R.string.introduction_response_accepted_sent,
|
||||
introducee)
|
||||
introducedAuthor)
|
||||
+ "\n\n" + ctx.getString(
|
||||
R.string.introduction_response_accepted_sent_info,
|
||||
introducee);
|
||||
introducedAuthor);
|
||||
} else {
|
||||
text = ctx.getString(
|
||||
R.string.introduction_response_declined_sent,
|
||||
r.getIntroducedAuthor().getName());
|
||||
introducedAuthor);
|
||||
}
|
||||
return new ConversationNoticeOutItem(text, r);
|
||||
} else {
|
||||
@@ -223,17 +227,17 @@ class ConversationVisitor implements PrivateMessageVisitor<ConversationItem> {
|
||||
text = ctx.getString(
|
||||
R.string.introduction_response_accepted_received,
|
||||
contactName.getValue(),
|
||||
r.getIntroducedAuthor().getName());
|
||||
introducedAuthor);
|
||||
} else if (r.isIntroducer()) {
|
||||
text = ctx.getString(
|
||||
R.string.introduction_response_declined_received,
|
||||
contactName.getValue(),
|
||||
r.getIntroducedAuthor().getName());
|
||||
introducedAuthor);
|
||||
} else {
|
||||
text = ctx.getString(
|
||||
R.string.introduction_response_declined_received_by_introducee,
|
||||
contactName.getValue(),
|
||||
r.getIntroducedAuthor().getName());
|
||||
introducedAuthor);
|
||||
}
|
||||
return new ConversationNoticeInItem(text, r);
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ import static android.view.View.VISIBLE;
|
||||
import static android.widget.Toast.LENGTH_SHORT;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||
import static org.briarproject.briar.android.util.UiUtils.getContactDisplayName;
|
||||
import static org.briarproject.briar.api.introduction.IntroductionConstants.MAX_INTRODUCTION_TEXT_LENGTH;
|
||||
|
||||
public class IntroductionMessageFragment extends BaseFragment
|
||||
@@ -148,8 +149,8 @@ public class IntroductionMessageFragment extends BaseFragment
|
||||
c2.getAuthor().getId().getBytes()));
|
||||
|
||||
// set contact names
|
||||
ui.contactName1.setText(c1.getAuthor().getName());
|
||||
ui.contactName2.setText(c2.getAuthor().getName());
|
||||
ui.contactName1.setText(getContactDisplayName(c1));
|
||||
ui.contactName2.setText(getContactDisplayName(c2));
|
||||
|
||||
// hide progress bar
|
||||
ui.progressBar.setVisibility(GONE);
|
||||
|
||||
@@ -36,24 +36,25 @@ class JoinMessageItemViewHolder
|
||||
if (item.isInitial()) {
|
||||
textView.setText(R.string.groups_member_created_you);
|
||||
} else {
|
||||
textView.setText(
|
||||
getContext().getString(R.string.groups_member_joined,
|
||||
item.getAuthor().getName()));
|
||||
String name = item.getAuthorName();
|
||||
textView.setText(getContext()
|
||||
.getString(R.string.groups_member_joined, name));
|
||||
}
|
||||
}
|
||||
|
||||
private void bind(JoinMessageItem item) {
|
||||
Context ctx = getContext();
|
||||
String name = item.getAuthorName();
|
||||
|
||||
if (item.isInitial()) {
|
||||
textView.setText(ctx.getString(R.string.groups_member_created,
|
||||
item.getAuthor().getName()));
|
||||
textView.setText(
|
||||
ctx.getString(R.string.groups_member_created, name));
|
||||
} else {
|
||||
if (item.getAuthorInfo().getStatus() == OURSELVES) {
|
||||
textView.setText(R.string.groups_member_joined_you);
|
||||
} else {
|
||||
textView.setText(ctx.getString(R.string.groups_member_joined,
|
||||
item.getAuthor().getName()));
|
||||
textView.setText(
|
||||
ctx.getString(R.string.groups_member_joined, name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@ import org.briarproject.briar.api.privategroup.invitation.GroupInvitationItem;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static org.briarproject.briar.android.util.UiUtils.getContactDisplayName;
|
||||
|
||||
class GroupInvitationViewHolder
|
||||
extends InvitationViewHolder<GroupInvitationItem> {
|
||||
|
||||
@@ -24,7 +26,7 @@ class GroupInvitationViewHolder
|
||||
|
||||
sharedBy.setText(
|
||||
sharedBy.getContext().getString(R.string.groups_created_by,
|
||||
item.getCreator().getAuthor().getName()));
|
||||
getContactDisplayName(item.getCreator())));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.briarproject.briar.android.privategroup.list;
|
||||
|
||||
import org.briarproject.bramble.api.identity.Author;
|
||||
import org.briarproject.bramble.api.identity.AuthorInfo;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.GroupId;
|
||||
import org.briarproject.briar.api.client.MessageTracker.GroupCount;
|
||||
@@ -12,12 +13,15 @@ import org.briarproject.briar.api.privategroup.PrivateGroup;
|
||||
class GroupItem {
|
||||
|
||||
private final PrivateGroup privateGroup;
|
||||
private final AuthorInfo authorInfo;
|
||||
private int messageCount, unreadCount;
|
||||
private long timestamp;
|
||||
private boolean dissolved;
|
||||
|
||||
GroupItem(PrivateGroup privateGroup, GroupCount count, boolean dissolved) {
|
||||
GroupItem(PrivateGroup privateGroup, AuthorInfo authorInfo,
|
||||
GroupCount count, boolean dissolved) {
|
||||
this.privateGroup = privateGroup;
|
||||
this.authorInfo = authorInfo;
|
||||
this.messageCount = count.getMsgCount();
|
||||
this.unreadCount = count.getUnreadCount();
|
||||
this.timestamp = count.getLatestMsgTime();
|
||||
@@ -46,6 +50,10 @@ class GroupItem {
|
||||
return privateGroup.getCreator();
|
||||
}
|
||||
|
||||
AuthorInfo getCreatorInfo() {
|
||||
return authorInfo;
|
||||
}
|
||||
|
||||
String getName() {
|
||||
return privateGroup.getName();
|
||||
}
|
||||
|
||||
@@ -2,12 +2,15 @@ package org.briarproject.briar.android.privategroup.list;
|
||||
|
||||
import android.support.annotation.CallSuper;
|
||||
|
||||
import org.briarproject.bramble.api.contact.ContactManager;
|
||||
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
||||
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.EventBus;
|
||||
import org.briarproject.bramble.api.event.EventListener;
|
||||
import org.briarproject.bramble.api.identity.AuthorId;
|
||||
import org.briarproject.bramble.api.identity.AuthorInfo;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||
@@ -30,7 +33,9 @@ import org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@@ -52,6 +57,7 @@ class GroupListControllerImpl extends DbControllerImpl
|
||||
|
||||
private final PrivateGroupManager groupManager;
|
||||
private final GroupInvitationManager groupInvitationManager;
|
||||
private final ContactManager contactManager;
|
||||
private final AndroidNotificationManager notificationManager;
|
||||
private final EventBus eventBus;
|
||||
|
||||
@@ -61,10 +67,12 @@ class GroupListControllerImpl extends DbControllerImpl
|
||||
GroupListControllerImpl(@DatabaseExecutor Executor dbExecutor,
|
||||
LifecycleManager lifecycleManager, PrivateGroupManager groupManager,
|
||||
GroupInvitationManager groupInvitationManager,
|
||||
ContactManager contactManager,
|
||||
AndroidNotificationManager notificationManager, EventBus eventBus) {
|
||||
super(dbExecutor, lifecycleManager);
|
||||
this.groupManager = groupManager;
|
||||
this.groupInvitationManager = groupInvitationManager;
|
||||
this.contactManager = contactManager;
|
||||
this.notificationManager = notificationManager;
|
||||
this.eventBus = eventBus;
|
||||
}
|
||||
@@ -153,12 +161,22 @@ class GroupListControllerImpl extends DbControllerImpl
|
||||
Collection<PrivateGroup> groups =
|
||||
groupManager.getPrivateGroups();
|
||||
List<GroupItem> items = new ArrayList<>(groups.size());
|
||||
Map<AuthorId, AuthorInfo> authorInfos = new HashMap<>();
|
||||
for (PrivateGroup g : groups) {
|
||||
try {
|
||||
GroupId id = g.getId();
|
||||
AuthorId authorId = g.getCreator().getId();
|
||||
AuthorInfo authorInfo;
|
||||
if (authorInfos.containsKey(authorId)) {
|
||||
authorInfo = authorInfos.get(authorId);
|
||||
} else {
|
||||
authorInfo = contactManager.getAuthorInfo(authorId);
|
||||
authorInfos.put(authorId, authorInfo);
|
||||
}
|
||||
GroupCount count = groupManager.getGroupCount(id);
|
||||
boolean dissolved = groupManager.isDissolved(id);
|
||||
items.add(new GroupItem(g, count, dissolved));
|
||||
items.add(
|
||||
new GroupItem(g, authorInfo, count, dissolved));
|
||||
} catch (NoSuchGroupException e) {
|
||||
// Continue
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import static android.view.View.GONE;
|
||||
import static android.view.View.VISIBLE;
|
||||
import static org.briarproject.briar.android.activity.BriarActivity.GROUP_ID;
|
||||
import static org.briarproject.briar.android.activity.BriarActivity.GROUP_NAME;
|
||||
import static org.briarproject.briar.android.util.UiUtils.getContactDisplayName;
|
||||
|
||||
@MethodsNotNullByDefault
|
||||
@ParametersNotNullByDefault
|
||||
@@ -60,8 +61,9 @@ class GroupViewHolder extends RecyclerView.ViewHolder {
|
||||
name.setText(group.getName());
|
||||
|
||||
// Creator
|
||||
creator.setText(ctx.getString(R.string.groups_created_by,
|
||||
group.getCreator().getName()));
|
||||
String creatorName = getContactDisplayName(group.getCreator(),
|
||||
group.getCreatorInfo().getAlias());
|
||||
creator.setText(ctx.getString(R.string.groups_created_by, creatorName));
|
||||
|
||||
if (!group.isDissolved()) {
|
||||
// full visibility
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.briarproject.briar.android.privategroup.memberlist;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
@@ -8,6 +9,8 @@ import android.view.ViewGroup;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.util.BriarAdapter;
|
||||
|
||||
import static org.briarproject.briar.android.util.UiUtils.getContactDisplayName;
|
||||
|
||||
class MemberListAdapter extends
|
||||
BriarAdapter<MemberListItem, MemberListItemHolder> {
|
||||
|
||||
@@ -15,8 +18,9 @@ class MemberListAdapter extends
|
||||
super(context, MemberListItem.class);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public MemberListItemHolder onCreateViewHolder(ViewGroup viewGroup,
|
||||
public MemberListItemHolder onCreateViewHolder(@NonNull ViewGroup viewGroup,
|
||||
int i) {
|
||||
View v = LayoutInflater.from(ctx).inflate(
|
||||
R.layout.list_item_group_member, viewGroup, false);
|
||||
@@ -24,13 +28,18 @@ class MemberListAdapter extends
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(MemberListItemHolder ui, int position) {
|
||||
public void onBindViewHolder(@NonNull MemberListItemHolder ui,
|
||||
int position) {
|
||||
ui.bind(items.get(position));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compare(MemberListItem m1, MemberListItem m2) {
|
||||
return m1.getMember().getName().compareTo(m2.getMember().getName());
|
||||
String n1 = getContactDisplayName(m1.getMember(),
|
||||
m1.getAuthorInfo().getAlias());
|
||||
String n2 = getContactDisplayName(m2.getMember(),
|
||||
m2.getAuthorInfo().getAlias());
|
||||
return n1.compareTo(n2);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -13,6 +13,7 @@ import org.briarproject.briar.android.view.AuthorView;
|
||||
import static android.view.View.GONE;
|
||||
import static android.view.View.VISIBLE;
|
||||
import static org.briarproject.bramble.api.identity.AuthorInfo.Status.OURSELVES;
|
||||
import static org.briarproject.briar.android.util.UiUtils.getContactDisplayName;
|
||||
|
||||
@UiThread
|
||||
@NotNullByDefault
|
||||
@@ -31,8 +32,7 @@ class MemberListItemHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
protected void bind(MemberListItem item) {
|
||||
// member name, avatar and author info
|
||||
author.setAuthor(item.getMember());
|
||||
author.setAuthorInfo(item.getAuthorInfo());
|
||||
author.setAuthor(item.getMember(), item.getAuthorInfo());
|
||||
|
||||
// online status of visible contacts
|
||||
if (item.getContactId() != null) {
|
||||
@@ -52,9 +52,10 @@ class MemberListItemHolder extends RecyclerView.ViewHolder {
|
||||
if (item.getStatus() == OURSELVES) {
|
||||
creator.setText(R.string.groups_member_created_you);
|
||||
} else {
|
||||
String name = getContactDisplayName(item.getMember(),
|
||||
item.getAuthorInfo().getAlias());
|
||||
creator.setText(creator.getContext()
|
||||
.getString(R.string.groups_member_created,
|
||||
item.getMember().getName()));
|
||||
.getString(R.string.groups_member_created, name));
|
||||
}
|
||||
} else {
|
||||
creator.setVisibility(GONE);
|
||||
|
||||
@@ -14,6 +14,7 @@ import javax.annotation.Nullable;
|
||||
import static org.briarproject.briar.android.privategroup.VisibilityHelper.getVisibilityIcon;
|
||||
import static org.briarproject.briar.android.privategroup.VisibilityHelper.getVisibilityString;
|
||||
import static org.briarproject.briar.android.util.UiUtils.GREY_OUT;
|
||||
import static org.briarproject.briar.android.util.UiUtils.getContactDisplayName;
|
||||
|
||||
@UiThread
|
||||
@NotNullByDefault
|
||||
@@ -36,7 +37,7 @@ class RevealableContactViewHolder
|
||||
icon.setImageResource(getVisibilityIcon(item.getVisibility()));
|
||||
info.setText(
|
||||
getVisibilityString(info.getContext(), item.getVisibility(),
|
||||
item.getContact().getAuthor().getName()));
|
||||
getContactDisplayName(item.getContact())));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -13,6 +13,8 @@ import java.util.Collection;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static org.briarproject.briar.android.util.UiUtils.getContactDisplayName;
|
||||
|
||||
class SharingInvitationViewHolder
|
||||
extends InvitationViewHolder<SharingInvitationItem> {
|
||||
|
||||
@@ -28,7 +30,7 @@ class SharingInvitationViewHolder
|
||||
|
||||
Collection<String> names = new ArrayList<>();
|
||||
for (Contact c : item.getNewSharers())
|
||||
names.add(c.getAuthor().getName());
|
||||
names.add(getContactDisplayName(c));
|
||||
sharedBy.setText(
|
||||
sharedBy.getContext().getString(R.string.shared_by_format,
|
||||
StringUtils.join(names, ", ")));
|
||||
|
||||
@@ -43,9 +43,8 @@ public abstract class BaseThreadItemViewHolder<I extends ThreadItem>
|
||||
public void bind(I item, ThreadItemListener<I> listener) {
|
||||
textView.setText(StringUtils.trim(item.getText()));
|
||||
|
||||
author.setAuthor(item.getAuthor());
|
||||
author.setAuthor(item.getAuthor(), item.getAuthorInfo());
|
||||
author.setDate(item.getTimestamp());
|
||||
author.setAuthorInfo(item.getAuthorInfo());
|
||||
|
||||
if (item.isHighlighted()) {
|
||||
layout.setActivated(true);
|
||||
|
||||
@@ -10,6 +10,7 @@ import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
|
||||
import static org.briarproject.briar.android.threaded.ThreadItemAdapter.UNDEFINED;
|
||||
import static org.briarproject.briar.android.util.UiUtils.getContactDisplayName;
|
||||
|
||||
@NotThreadSafe
|
||||
@NotNullByDefault
|
||||
@@ -70,6 +71,13 @@ public abstract class ThreadItem implements MessageNode {
|
||||
return authorInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the author's name, with an alias if one exists.
|
||||
*/
|
||||
public String getAuthorName() {
|
||||
return getContactDisplayName(author, authorInfo.getAlias());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLevel(int level) {
|
||||
this.level = level;
|
||||
|
||||
@@ -33,7 +33,9 @@ import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.acra.ACRA;
|
||||
import org.briarproject.bramble.api.contact.Contact;
|
||||
import org.briarproject.bramble.api.contact.ContactId;
|
||||
import org.briarproject.bramble.api.identity.Author;
|
||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||
import org.briarproject.bramble.api.system.AndroidExecutor;
|
||||
@@ -74,6 +76,17 @@ public class UiUtils {
|
||||
public static final int TEASER_LENGTH = 320;
|
||||
public static final float GREY_OUT = 0.5f;
|
||||
|
||||
public static String getContactDisplayName(Author author,
|
||||
@Nullable String alias) {
|
||||
String name = author.getName();
|
||||
if (alias == null) return name;
|
||||
else return String.format("%s (%s)", alias, name);
|
||||
}
|
||||
|
||||
public static String getContactDisplayName(Contact c) {
|
||||
return getContactDisplayName(c.getAuthor(), c.getAlias());
|
||||
}
|
||||
|
||||
public static void setError(TextInputLayout til, @Nullable String error,
|
||||
boolean set) {
|
||||
if (set) {
|
||||
@@ -127,7 +140,9 @@ public class UiUtils {
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static Spanned getSpanned(String s) {
|
||||
public static Spanned getSpanned(@Nullable String s) {
|
||||
// TODO move to HtmlCompat #1435
|
||||
// https://commonsware.com/blog/2018/05/29/at-last-htmlcompat.html
|
||||
return Html.fromHtml(s);
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ import static android.graphics.Typeface.BOLD;
|
||||
import static android.util.TypedValue.COMPLEX_UNIT_PX;
|
||||
import static org.briarproject.bramble.api.identity.AuthorInfo.Status.NONE;
|
||||
import static org.briarproject.bramble.api.identity.AuthorInfo.Status.OURSELVES;
|
||||
import static org.briarproject.briar.android.util.UiUtils.getContactDisplayName;
|
||||
import static org.briarproject.briar.android.util.UiUtils.resolveAttribute;
|
||||
|
||||
@UiThread
|
||||
@@ -70,16 +71,12 @@ public class AuthorView extends ConstraintLayout {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public void setAuthor(Author author) {
|
||||
authorName.setText(author.getName());
|
||||
public void setAuthor(Author author, AuthorInfo authorInfo) {
|
||||
authorName
|
||||
.setText(getContactDisplayName(author, authorInfo.getAlias()));
|
||||
IdenticonDrawable d = new IdenticonDrawable(author.getId().getBytes());
|
||||
avatar.setImageDrawable(d);
|
||||
|
||||
invalidate();
|
||||
requestLayout();
|
||||
}
|
||||
|
||||
public void setAuthorInfo(AuthorInfo authorInfo) {
|
||||
if (authorInfo.getStatus() != NONE) {
|
||||
trustIndicator.setTrustLevel(authorInfo.getStatus());
|
||||
trustIndicator.setVisibility(VISIBLE);
|
||||
@@ -123,7 +120,7 @@ public class AuthorView extends ConstraintLayout {
|
||||
*
|
||||
* Attention: RSS_FEED and RSS_FEED_REBLOGGED change the avatar
|
||||
* and override the one set by
|
||||
* {@link AuthorView#setAuthor(Author)}.
|
||||
* {@link AuthorView#setAuthor(Author, AuthorInfo)}.
|
||||
*/
|
||||
public void setPersona(int persona) {
|
||||
switch (persona) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.briarproject.briar.api.introduction;
|
||||
|
||||
import org.briarproject.bramble.api.identity.Author;
|
||||
import org.briarproject.bramble.api.identity.AuthorInfo;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.GroupId;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
@@ -15,19 +16,24 @@ import javax.annotation.concurrent.Immutable;
|
||||
@NotNullByDefault
|
||||
public class IntroductionRequest extends PrivateRequest<Author> {
|
||||
|
||||
private final boolean contact;
|
||||
private final AuthorInfo authorInfo;
|
||||
|
||||
public IntroductionRequest(MessageId messageId, GroupId groupId,
|
||||
long time, boolean local, boolean sent, boolean seen, boolean read,
|
||||
SessionId sessionId, Author author, @Nullable String text,
|
||||
boolean answered, boolean contact) {
|
||||
boolean answered, AuthorInfo authorInfo) {
|
||||
super(messageId, groupId, time, local, sent, seen, read, sessionId,
|
||||
author, text, answered);
|
||||
this.contact = contact;
|
||||
this.authorInfo = authorInfo;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getAlias() {
|
||||
return authorInfo.getAlias();
|
||||
}
|
||||
|
||||
public boolean isContact() {
|
||||
return contact;
|
||||
return authorInfo.getStatus().isContact();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.briarproject.briar.api.introduction;
|
||||
|
||||
import org.briarproject.bramble.api.identity.Author;
|
||||
import org.briarproject.bramble.api.identity.AuthorInfo;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.GroupId;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
@@ -17,14 +18,17 @@ import static org.briarproject.briar.api.introduction.Role.INTRODUCER;
|
||||
public class IntroductionResponse extends PrivateResponse {
|
||||
|
||||
private final Author introducedAuthor;
|
||||
private final AuthorInfo introducedAuthorInfo;
|
||||
private final Role ourRole;
|
||||
|
||||
public IntroductionResponse(MessageId messageId, GroupId groupId, long time,
|
||||
boolean local, boolean sent, boolean seen, boolean read,
|
||||
SessionId sessionId, boolean accepted, Author author, Role role) {
|
||||
SessionId sessionId, boolean accepted, Author author,
|
||||
AuthorInfo introducedAuthorInfo, Role role) {
|
||||
super(messageId, groupId, time, local, sent, seen, read, sessionId,
|
||||
accepted);
|
||||
this.introducedAuthor = author;
|
||||
this.introducedAuthorInfo = introducedAuthorInfo;
|
||||
this.ourRole = role;
|
||||
}
|
||||
|
||||
@@ -32,6 +36,10 @@ public class IntroductionResponse extends PrivateResponse {
|
||||
return introducedAuthor;
|
||||
}
|
||||
|
||||
public AuthorInfo getIntroducedAuthorInfo() {
|
||||
return introducedAuthorInfo;
|
||||
}
|
||||
|
||||
public boolean isIntroducer() {
|
||||
return ourRole == INTRODUCER;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.db.Transaction;
|
||||
import org.briarproject.bramble.api.identity.Author;
|
||||
import org.briarproject.bramble.api.identity.AuthorId;
|
||||
import org.briarproject.bramble.api.identity.AuthorInfo;
|
||||
import org.briarproject.bramble.api.identity.IdentityManager;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.plugin.TransportId;
|
||||
@@ -149,11 +150,13 @@ abstract class AbstractProtocolEngine<S extends Session>
|
||||
throws DbException {
|
||||
AuthorId localAuthorId = identityManager.getLocalAuthor(txn).getId();
|
||||
Contact c = contactManager.getContact(txn, sender, localAuthorId);
|
||||
AuthorInfo otherAuthorInfo =
|
||||
contactManager.getAuthorInfo(txn, otherAuthor.getId());
|
||||
IntroductionResponse response =
|
||||
new IntroductionResponse(m.getMessageId(), m.getGroupId(),
|
||||
m.getTimestamp(), false, false, false, false,
|
||||
s.getSessionId(), m instanceof AcceptMessage,
|
||||
otherAuthor, s.getRole());
|
||||
otherAuthor, otherAuthorInfo, s.getRole());
|
||||
IntroductionResponseReceivedEvent e =
|
||||
new IntroductionResponseReceivedEvent(response, c.getId());
|
||||
txn.attach(e);
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.briarproject.bramble.api.db.ContactExistsException;
|
||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.db.Transaction;
|
||||
import org.briarproject.bramble.api.identity.AuthorInfo;
|
||||
import org.briarproject.bramble.api.identity.IdentityManager;
|
||||
import org.briarproject.bramble.api.identity.LocalAuthor;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
@@ -251,12 +252,12 @@ class IntroduceeProtocolEngine
|
||||
LocalAuthor localAuthor = identityManager.getLocalAuthor(txn);
|
||||
Contact c = contactManager.getContact(txn, s.getIntroducer().getId(),
|
||||
localAuthor.getId());
|
||||
boolean contactExists = contactManager
|
||||
.contactExists(txn, m.getAuthor().getId(), localAuthor.getId());
|
||||
AuthorInfo authorInfo =
|
||||
contactManager.getAuthorInfo(txn, m.getAuthor().getId());
|
||||
IntroductionRequest request = new IntroductionRequest(m.getMessageId(),
|
||||
m.getGroupId(), m.getTimestamp(), false, false, false, false,
|
||||
s.getSessionId(), m.getAuthor(), m.getText(), false,
|
||||
contactExists);
|
||||
authorInfo);
|
||||
IntroductionRequestReceivedEvent e =
|
||||
new IntroductionRequestReceivedEvent(request, c.getId());
|
||||
txn.attach(e);
|
||||
|
||||
@@ -15,6 +15,8 @@ import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.db.Metadata;
|
||||
import org.briarproject.bramble.api.db.Transaction;
|
||||
import org.briarproject.bramble.api.identity.Author;
|
||||
import org.briarproject.bramble.api.identity.AuthorId;
|
||||
import org.briarproject.bramble.api.identity.AuthorInfo;
|
||||
import org.briarproject.bramble.api.identity.IdentityManager;
|
||||
import org.briarproject.bramble.api.identity.LocalAuthor;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
@@ -39,6 +41,7 @@ import org.briarproject.briar.introduction.IntroducerSession.Introducee;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
@@ -408,6 +411,7 @@ class IntroductionManagerImpl extends ConversationClientImpl
|
||||
.getMessageMetadataAsDictionary(txn, contactGroupId, query);
|
||||
List<PrivateMessageHeader> messages =
|
||||
new ArrayList<>(results.size());
|
||||
Map<AuthorId, AuthorInfo> authorInfos = new HashMap<>();
|
||||
for (Entry<MessageId, BdfDictionary> e : results.entrySet()) {
|
||||
MessageId m = e.getKey();
|
||||
MessageMetadata meta =
|
||||
@@ -417,17 +421,14 @@ class IntroductionManagerImpl extends ConversationClientImpl
|
||||
if (ss == null) throw new AssertionError();
|
||||
MessageType type = meta.getMessageType();
|
||||
if (type == REQUEST) {
|
||||
messages.add(
|
||||
parseInvitationRequest(txn, contactGroupId, m,
|
||||
meta, status, ss.bdfSession));
|
||||
messages.add(parseInvitationRequest(txn, contactGroupId, m,
|
||||
meta, status, ss.bdfSession, authorInfos));
|
||||
} else if (type == ACCEPT) {
|
||||
messages.add(
|
||||
parseInvitationResponse(contactGroupId, m, meta,
|
||||
status, ss.bdfSession, true));
|
||||
messages.add(parseInvitationResponse(txn, contactGroupId, m,
|
||||
meta, status, ss.bdfSession, authorInfos, true));
|
||||
} else if (type == DECLINE) {
|
||||
messages.add(
|
||||
parseInvitationResponse(contactGroupId, m, meta,
|
||||
status, ss.bdfSession, false));
|
||||
messages.add(parseInvitationResponse(txn, contactGroupId, m,
|
||||
meta, status, ss.bdfSession, authorInfos, false));
|
||||
}
|
||||
}
|
||||
return messages;
|
||||
@@ -438,43 +439,41 @@ class IntroductionManagerImpl extends ConversationClientImpl
|
||||
|
||||
private IntroductionRequest parseInvitationRequest(Transaction txn,
|
||||
GroupId contactGroupId, MessageId m, MessageMetadata meta,
|
||||
MessageStatus status, BdfDictionary bdfSession)
|
||||
MessageStatus status, BdfDictionary bdfSession,
|
||||
Map<AuthorId, AuthorInfo> authorInfos)
|
||||
throws DbException, FormatException {
|
||||
Role role = sessionParser.getRole(bdfSession);
|
||||
SessionId sessionId;
|
||||
Author author;
|
||||
if (role == INTRODUCER) {
|
||||
IntroducerSession session =
|
||||
sessionParser.parseIntroducerSession(bdfSession);
|
||||
sessionId = session.getSessionId();
|
||||
if (contactGroupId.equals(session.getIntroduceeA().groupId)) {
|
||||
author = session.getIntroduceeB().author;
|
||||
} else {
|
||||
author = session.getIntroduceeA().author;
|
||||
}
|
||||
} else if (role == INTRODUCEE) {
|
||||
IntroduceeSession session = sessionParser
|
||||
.parseIntroduceeSession(contactGroupId, bdfSession);
|
||||
sessionId = session.getSessionId();
|
||||
author = session.getRemote().author;
|
||||
} else throw new AssertionError();
|
||||
Message msg = clientHelper.getMessage(txn, m);
|
||||
BdfList body = clientHelper.toList(msg);
|
||||
RequestMessage rm = messageParser.parseRequestMessage(msg, body);
|
||||
String text = rm.getText();
|
||||
LocalAuthor localAuthor = identityManager.getLocalAuthor(txn);
|
||||
boolean contactExists = contactManager
|
||||
.contactExists(txn, rm.getAuthor().getId(),
|
||||
localAuthor.getId());
|
||||
Author author = rm.getAuthor();
|
||||
AuthorInfo authorInfo = authorInfos.get(author.getId());
|
||||
if (authorInfo == null) {
|
||||
authorInfo = contactManager.getAuthorInfo(txn, author.getId());
|
||||
authorInfos.put(author.getId(), authorInfo);
|
||||
}
|
||||
return new IntroductionRequest(m, contactGroupId, meta.getTimestamp(),
|
||||
meta.isLocal(), status.isSent(), status.isSeen(), meta.isRead(),
|
||||
sessionId, author, text, !meta.isAvailableToAnswer(),
|
||||
contactExists);
|
||||
authorInfo);
|
||||
}
|
||||
|
||||
private IntroductionResponse parseInvitationResponse(GroupId contactGroupId,
|
||||
MessageId m, MessageMetadata meta, MessageStatus status,
|
||||
BdfDictionary bdfSession, boolean accept) throws FormatException {
|
||||
private IntroductionResponse parseInvitationResponse(Transaction txn,
|
||||
GroupId contactGroupId, MessageId m, MessageMetadata meta,
|
||||
MessageStatus status, BdfDictionary bdfSession,
|
||||
Map<AuthorId, AuthorInfo> authorInfos, boolean accept)
|
||||
throws FormatException, DbException {
|
||||
Role role = sessionParser.getRole(bdfSession);
|
||||
SessionId sessionId;
|
||||
Author author;
|
||||
@@ -493,9 +492,14 @@ class IntroductionManagerImpl extends ConversationClientImpl
|
||||
sessionId = session.getSessionId();
|
||||
author = session.getRemote().author;
|
||||
} else throw new AssertionError();
|
||||
AuthorInfo authorInfo = authorInfos.get(author.getId());
|
||||
if (authorInfo == null) {
|
||||
authorInfo = contactManager.getAuthorInfo(txn, author.getId());
|
||||
authorInfos.put(author.getId(), authorInfo);
|
||||
}
|
||||
return new IntroductionResponse(m, contactGroupId, meta.getTimestamp(),
|
||||
meta.isLocal(), status.isSent(), status.isSeen(), meta.isRead(),
|
||||
sessionId, accept, author, role);
|
||||
sessionId, accept, author, authorInfo, role);
|
||||
}
|
||||
|
||||
private void removeSessionWithIntroducer(Transaction txn,
|
||||
|
||||
@@ -174,6 +174,10 @@ public class TestDataCreatorImpl implements TestDataCreator {
|
||||
ContactId contactId = contactManager
|
||||
.addContact(txn, author, localAuthorId, secretKey,
|
||||
timestamp, true, verified, true);
|
||||
if (random.nextBoolean()) {
|
||||
contactManager
|
||||
.setContactAlias(txn, contactId, getRandomAuthorName());
|
||||
}
|
||||
transportPropertyManager.addRemoteProperties(txn, contactId, props);
|
||||
contact = db.getContact(txn, contactId);
|
||||
db.commitTransaction(txn);
|
||||
@@ -202,10 +206,13 @@ public class TestDataCreatorImpl implements TestDataCreator {
|
||||
return authorFactory.createLocalAuthor(name, publicKey, privateKey);
|
||||
}
|
||||
|
||||
private LocalAuthor getRandomAuthor() {
|
||||
private String getRandomAuthorName() {
|
||||
int i = random.nextInt(AUTHOR_NAMES.length);
|
||||
String authorName = AUTHOR_NAMES[i];
|
||||
return getAuthor(authorName);
|
||||
return AUTHOR_NAMES[i];
|
||||
}
|
||||
|
||||
private LocalAuthor getRandomAuthor() {
|
||||
return getAuthor(getRandomAuthorName());
|
||||
}
|
||||
|
||||
private SecretKey getSecretKey() {
|
||||
|
||||
@@ -7,6 +7,9 @@ import io.javalin.json.JavalinJson.toJson
|
||||
import io.mockk.*
|
||||
import org.briarproject.bramble.api.contact.ContactId
|
||||
import org.briarproject.bramble.api.db.NoSuchContactException
|
||||
import org.briarproject.bramble.api.identity.AuthorInfo
|
||||
import org.briarproject.bramble.api.identity.AuthorInfo.Status.UNVERIFIED
|
||||
import org.briarproject.bramble.api.identity.AuthorInfo.Status.VERIFIED
|
||||
import org.briarproject.bramble.test.ImmediateExecutor
|
||||
import org.briarproject.bramble.test.TestUtils.getRandomId
|
||||
import org.briarproject.bramble.util.StringUtils.getRandomString
|
||||
@@ -61,7 +64,7 @@ internal class MessagingControllerImplTest : ControllerTest() {
|
||||
fun listIntroductionRequest() {
|
||||
val request = IntroductionRequest(
|
||||
message.id, group.id, timestamp, true, true, false, true, sessionId, author, text,
|
||||
false, false
|
||||
false, AuthorInfo(UNVERIFIED)
|
||||
)
|
||||
|
||||
expectGetContact()
|
||||
@@ -200,7 +203,7 @@ internal class MessagingControllerImplTest : ControllerTest() {
|
||||
fun testIntroductionRequestWithNullText() {
|
||||
val request = IntroductionRequest(
|
||||
message.id, group.id, timestamp, true, true, false, true, sessionId, author, null,
|
||||
false, false
|
||||
false, AuthorInfo(VERIFIED)
|
||||
)
|
||||
val json = """
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user