Commit 2c2596af authored by akwizgran's avatar akwizgran

Merge branch 'conversation-manager' into 'master'

Use ConversationManager for private message retrieval

See merge request !912
parents d1be14ef 7d479063
package org.briarproject.bramble.api;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
public interface Nameable {
String getName();
}
package org.briarproject.bramble.api.identity;
import org.briarproject.bramble.api.Nameable;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.util.StringUtils;
......@@ -13,7 +14,7 @@ import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_K
*/
@Immutable
@NotNullByDefault
public class Author {
public class Author implements Nameable {
public enum Status {
NONE, ANONYMOUS, UNKNOWN, UNVERIFIED, VERIFIED, OURSELVES
......
......@@ -41,13 +41,9 @@ import org.briarproject.briar.android.util.BriarNotificationBuilder;
import org.briarproject.briar.api.android.AndroidNotificationManager;
import org.briarproject.briar.api.blog.event.BlogPostAddedEvent;
import org.briarproject.briar.api.forum.event.ForumPostReceivedEvent;
import org.briarproject.briar.api.introduction.event.IntroductionRequestReceivedEvent;
import org.briarproject.briar.api.introduction.event.IntroductionResponseReceivedEvent;
import org.briarproject.briar.api.introduction.event.IntroductionSucceededEvent;
import org.briarproject.briar.api.messaging.event.PrivateMessageReceivedEvent;
import org.briarproject.briar.api.privategroup.event.GroupMessageAddedEvent;
import org.briarproject.briar.api.sharing.event.InvitationRequestReceivedEvent;
import org.briarproject.briar.api.sharing.event.InvitationResponseReceivedEvent;
import java.util.Set;
import java.util.concurrent.Callable;
......@@ -235,19 +231,6 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
} else if (e instanceof BlogPostAddedEvent) {
BlogPostAddedEvent b = (BlogPostAddedEvent) e;
showBlogPostNotification(b.getGroupId());
} else if (e instanceof IntroductionRequestReceivedEvent) {
ContactId c = ((IntroductionRequestReceivedEvent) e).getContactId();
showContactNotification(c);
} else if (e instanceof IntroductionResponseReceivedEvent) {
ContactId c =
((IntroductionResponseReceivedEvent) e).getContactId();
showContactNotification(c);
} else if (e instanceof InvitationRequestReceivedEvent) {
ContactId c = ((InvitationRequestReceivedEvent) e).getContactId();
showContactNotification(c);
} else if (e instanceof InvitationResponseReceivedEvent) {
ContactId c = ((InvitationResponseReceivedEvent) e).getContactId();
showContactNotification(c);
} else if (e instanceof IntroductionSucceededEvent) {
showIntroductionNotification();
}
......
......@@ -21,11 +21,11 @@ import org.briarproject.briar.android.controller.ActivityLifecycleController;
import org.briarproject.briar.android.controller.handler.ResultExceptionHandler;
import org.briarproject.briar.api.android.AndroidNotificationManager;
import org.briarproject.briar.api.blog.Blog;
import org.briarproject.briar.api.blog.BlogInvitationResponse;
import org.briarproject.briar.api.blog.BlogManager;
import org.briarproject.briar.api.blog.BlogSharingManager;
import org.briarproject.briar.api.blog.event.BlogInvitationResponseReceivedEvent;
import org.briarproject.briar.api.blog.event.BlogPostAddedEvent;
import org.briarproject.briar.api.sharing.InvitationResponse;
import org.briarproject.briar.api.sharing.event.ContactLeftShareableEvent;
import java.util.ArrayList;
......@@ -107,7 +107,7 @@ class BlogControllerImpl extends BaseControllerImpl
} else if (e instanceof BlogInvitationResponseReceivedEvent) {
BlogInvitationResponseReceivedEvent b =
(BlogInvitationResponseReceivedEvent) e;
InvitationResponse r = b.getResponse();
BlogInvitationResponse r = b.getMessageHeader();
if (r.getShareableId().equals(groupId) && r.wasAccepted()) {
LOG.info("Blog invitation accepted");
onBlogInvitationAccepted(b.getContactId());
......
......@@ -36,19 +36,10 @@ import org.briarproject.briar.android.fragment.BaseFragment;
import org.briarproject.briar.android.keyagreement.ContactExchangeActivity;
import org.briarproject.briar.android.view.BriarRecyclerView;
import org.briarproject.briar.api.android.AndroidNotificationManager;
import org.briarproject.briar.api.client.BaseMessageHeader;
import org.briarproject.briar.api.client.MessageTracker.GroupCount;
import org.briarproject.briar.api.introduction.IntroductionRequest;
import org.briarproject.briar.api.introduction.IntroductionResponse;
import org.briarproject.briar.api.introduction.event.IntroductionRequestReceivedEvent;
import org.briarproject.briar.api.introduction.event.IntroductionResponseReceivedEvent;
import org.briarproject.briar.api.messaging.ConversationManager;
import org.briarproject.briar.api.messaging.PrivateMessageHeader;
import org.briarproject.briar.api.messaging.event.PrivateMessageReceivedEvent;
import org.briarproject.briar.api.sharing.InvitationRequest;
import org.briarproject.briar.api.sharing.InvitationResponse;
import org.briarproject.briar.api.sharing.event.InvitationRequestReceivedEvent;
import org.briarproject.briar.api.sharing.event.InvitationResponseReceivedEvent;
import java.util.ArrayList;
import java.util.List;
......@@ -256,40 +247,16 @@ public class ContactListFragment extends BaseFragment implements EventListener {
PrivateMessageReceivedEvent p = (PrivateMessageReceivedEvent) e;
PrivateMessageHeader h = p.getMessageHeader();
updateItem(p.getContactId(), h);
} else if (e instanceof IntroductionRequestReceivedEvent) {
LOG.info("Introduction request received, updating item");
IntroductionRequestReceivedEvent m =
(IntroductionRequestReceivedEvent) e;
IntroductionRequest ir = m.getIntroductionRequest();
updateItem(m.getContactId(), ir);
} else if (e instanceof IntroductionResponseReceivedEvent) {
LOG.info("Introduction response received, updating item");
IntroductionResponseReceivedEvent m =
(IntroductionResponseReceivedEvent) e;
IntroductionResponse ir = m.getIntroductionResponse();
updateItem(m.getContactId(), ir);
} else if (e instanceof InvitationRequestReceivedEvent) {
LOG.info("Invitation Request received, update item");
InvitationRequestReceivedEvent m =
(InvitationRequestReceivedEvent) e;
InvitationRequest ir = m.getRequest();
updateItem(m.getContactId(), ir);
} else if (e instanceof InvitationResponseReceivedEvent) {
LOG.info("Invitation response received, updating item");
InvitationResponseReceivedEvent m =
(InvitationResponseReceivedEvent) e;
InvitationResponse ir = m.getResponse();
updateItem(m.getContactId(), ir);
}
}
private void updateItem(ContactId c, BaseMessageHeader h) {
private void updateItem(ContactId c, PrivateMessageHeader h) {
runOnUiThreadUnlessDestroyed(() -> {
adapter.incrementRevision();
int position = adapter.findItemPosition(c);
ContactListItem item = adapter.getItemAt(position);
if (item != null) {
ConversationItem i = ConversationItem.from(getContext(), h);
ConversationItem i = ConversationItem.from(getContext(), "", h);
item.addMessage(i);
adapter.updateItemAt(position, item);
}
......
package org.briarproject.briar.android.contact;
import android.content.Context;
import android.support.annotation.LayoutRes;
import android.support.annotation.StringRes;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.briar.R;
import org.briarproject.briar.api.blog.BlogInvitationResponse;
import org.briarproject.briar.api.forum.ForumInvitationResponse;
import org.briarproject.briar.api.introduction.IntroductionResponse;
import org.briarproject.briar.api.messaging.PrivateResponse;
import org.briarproject.briar.api.privategroup.invitation.GroupInvitationResponse;
import javax.annotation.Nullable;
import javax.annotation.concurrent.NotThreadSafe;
......@@ -24,6 +31,13 @@ class ConversationNoticeInItem extends ConversationItem {
this.msgText = msgText;
}
public ConversationNoticeInItem(Context ctx, String contactName,
PrivateResponse r) {
super(r.getId(), r.getGroupId(), getText(ctx, contactName, r),
r.getTimestamp(), r.isRead());
this.msgText = null;
}
@Nullable
String getMsgText() {
return msgText;
......@@ -40,4 +54,54 @@ class ConversationNoticeInItem extends ConversationItem {
return R.layout.list_item_conversation_notice_in;
}
private static String getText(Context ctx, String contactName,
PrivateResponse r) {
if (r.wasAccepted()) {
if (r instanceof IntroductionResponse) {
IntroductionResponse ir = (IntroductionResponse) r;
return ctx.getString(
R.string.introduction_response_accepted_received,
contactName, ir.getIntroducedAuthor().getName());
} else if (r instanceof ForumInvitationResponse) {
return ctx.getString(
R.string.forum_invitation_response_accepted_received,
contactName);
} else if (r instanceof BlogInvitationResponse) {
return ctx.getString(
R.string.blogs_sharing_response_accepted_received,
contactName);
} else if (r instanceof GroupInvitationResponse) {
return ctx.getString(
R.string.groups_invitations_response_accepted_received,
contactName);
}
} else {
if (r instanceof IntroductionResponse) {
IntroductionResponse ir = (IntroductionResponse) r;
@StringRes int res;
if (ir.isIntroducer()) {
res = R.string.introduction_response_declined_received;
} else {
res =
R.string.introduction_response_declined_received_by_introducee;
}
return ctx.getString(res, contactName,
ir.getIntroducedAuthor().getName());
} else if (r instanceof ForumInvitationResponse) {
return ctx.getString(
R.string.forum_invitation_response_declined_received,
contactName);
} else if (r instanceof BlogInvitationResponse) {
return ctx.getString(
R.string.blogs_sharing_response_declined_received,
contactName);
} else if (r instanceof GroupInvitationResponse) {
return ctx.getString(
R.string.groups_invitations_response_declined_received,
contactName);
}
}
throw new IllegalArgumentException("Unknown PrivateResponse");
}
}
package org.briarproject.briar.android.contact;
import android.content.Context;
import android.support.annotation.LayoutRes;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.briar.R;
import org.briarproject.briar.api.blog.BlogInvitationRequest;
import org.briarproject.briar.api.blog.BlogInvitationResponse;
import org.briarproject.briar.api.forum.ForumInvitationRequest;
import org.briarproject.briar.api.forum.ForumInvitationResponse;
import org.briarproject.briar.api.introduction.IntroductionRequest;
import org.briarproject.briar.api.introduction.IntroductionResponse;
import org.briarproject.briar.api.messaging.PrivateRequest;
import org.briarproject.briar.api.messaging.PrivateResponse;
import org.briarproject.briar.api.privategroup.invitation.GroupInvitationRequest;
import org.briarproject.briar.api.privategroup.invitation.GroupInvitationResponse;
import javax.annotation.Nullable;
import javax.annotation.concurrent.NotThreadSafe;
......@@ -17,11 +26,18 @@ class ConversationNoticeOutItem extends ConversationOutItem {
@Nullable
private final String msgText;
ConversationNoticeOutItem(MessageId id, GroupId groupId,
String text, @Nullable String msgText, long time,
boolean sent, boolean seen) {
super(id, groupId, text, time, sent, seen);
this.msgText = msgText;
ConversationNoticeOutItem(Context ctx, String contactName,
PrivateRequest r) {
super(r.getId(), r.getGroupId(), getText(ctx, contactName, r),
r.getTimestamp(), r.isSent(), r.isSeen());
this.msgText = r.getMessage();
}
ConversationNoticeOutItem(Context ctx, String contactName,
PrivateResponse r) {
super(r.getId(), r.getGroupId(), getText(ctx, contactName, r),
r.getTimestamp(), r.isSent(), r.isSeen());
this.msgText = null;
}
@Nullable
......@@ -35,4 +51,57 @@ class ConversationNoticeOutItem extends ConversationOutItem {
return R.layout.list_item_conversation_notice_out;
}
private static String getText(Context ctx, String contactName,
PrivateRequest r) {
if (r instanceof IntroductionRequest) {
return ctx.getString(R.string.introduction_request_sent,
contactName, r.getName());
} else if (r instanceof ForumInvitationRequest) {
return ctx.getString(R.string.forum_invitation_sent,
r.getName(), contactName);
} else if (r instanceof BlogInvitationRequest) {
return ctx.getString(R.string.blogs_sharing_invitation_sent,
r.getName(), contactName);
} else if (r instanceof GroupInvitationRequest) {
return ctx.getString(R.string.groups_invitations_invitation_sent,
contactName, r.getName());
}
throw new IllegalArgumentException("Unknown PrivateRequest");
}
private static String getText(Context ctx, String contactName,
PrivateResponse r) {
if (r.wasAccepted()) {
if (r instanceof IntroductionResponse) {
String name = ((IntroductionResponse) r).getIntroducedAuthor()
.getName();
return ctx.getString(
R.string.introduction_response_accepted_sent,
name) + "\n\n" + ctx.getString(
R.string.introduction_response_accepted_sent_info,
name);
} else if (r instanceof ForumInvitationResponse) {
return ctx.getString(R.string.forum_invitation_response_accepted_sent, contactName);
} else if (r instanceof BlogInvitationResponse) {
return ctx.getString(R.string.blogs_sharing_response_accepted_sent, contactName);
} else if (r instanceof GroupInvitationResponse) {
return ctx.getString(R.string.groups_invitations_response_accepted_sent, contactName);
}
} else {
if (r instanceof IntroductionResponse) {
String name = ((IntroductionResponse) r).getIntroducedAuthor()
.getName();
return ctx.getString(
R.string.introduction_response_declined_sent, name);
} else if (r instanceof ForumInvitationResponse) {
return ctx.getString(R.string.forum_invitation_response_declined_sent, contactName);
} else if (r instanceof BlogInvitationResponse) {
return ctx.getString(R.string.blogs_sharing_response_declined_sent, contactName);
} else if (r instanceof GroupInvitationResponse) {
return ctx.getString(R.string.groups_invitations_response_declined_sent, contactName);
}
}
throw new IllegalArgumentException("Unknown PrivateResponse");
}
}
package org.briarproject.briar.android.contact;
import android.content.Context;
import android.support.annotation.LayoutRes;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.briar.R;
import org.briarproject.briar.api.blog.BlogInvitationRequest;
import org.briarproject.briar.api.client.SessionId;
import org.briarproject.briar.api.forum.ForumInvitationRequest;
import org.briarproject.briar.api.introduction.IntroductionRequest;
import org.briarproject.briar.api.messaging.PrivateRequest;
import org.briarproject.briar.api.privategroup.invitation.GroupInvitationRequest;
import org.briarproject.briar.api.sharing.InvitationRequest;
import org.briarproject.briar.api.sharing.Shareable;
import javax.annotation.Nullable;
import javax.annotation.concurrent.NotThreadSafe;
import static org.briarproject.briar.android.contact.ConversationRequestItem.RequestType.BLOG;
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;
@NotThreadSafe
@NotNullByDefault
class ConversationRequestItem extends ConversationNoticeInItem {
......@@ -24,17 +36,20 @@ class ConversationRequestItem extends ConversationNoticeInItem {
private final boolean canBeOpened;
private boolean answered;
ConversationRequestItem(MessageId id, GroupId groupId,
RequestType requestType, SessionId sessionId, String text,
@Nullable String msgText, long time, boolean read,
@Nullable GroupId requestedGroupId, boolean answered,
boolean canBeOpened) {
super(id, groupId, text, msgText, time, read);
this.requestType = requestType;
this.sessionId = sessionId;
this.requestedGroupId = requestedGroupId;
this.answered = answered;
this.canBeOpened = canBeOpened;
ConversationRequestItem(Context ctx, String contactName,
PrivateRequest r) {
super(r.getId(), r.getGroupId(), getText(ctx, contactName, r),
r.getMessage(), r.getTimestamp(), r.isRead());
this.requestType = getType(r);
this.sessionId = r.getSessionId();
this.answered = r.wasAnswered();
if (r instanceof InvitationRequest) {
this.requestedGroupId = ((Shareable) r.getNameable()).getId();
this.canBeOpened = ((InvitationRequest) r).canBeOpened();
} else {
this.requestedGroupId = null;
this.canBeOpened = false;
}
}
RequestType getRequestType() {
......@@ -54,8 +69,8 @@ class ConversationRequestItem extends ConversationNoticeInItem {
return answered;
}
void setAnswered(boolean answered) {
this.answered = answered;
void setAnswered() {
this.answered = true;
}
public boolean canBeOpened() {
......@@ -68,4 +83,46 @@ class ConversationRequestItem extends ConversationNoticeInItem {
return R.layout.list_item_conversation_request;
}
private static String getText(Context ctx, String contactName,
PrivateRequest r) {
if (r instanceof IntroductionRequest) {
if (r.wasAnswered()) {
return ctx.getString(
R.string.introduction_request_answered_received,
contactName, r.getName());
} else if (((IntroductionRequest) r).isContact()) {
return ctx.getString(
R.string.introduction_request_exists_received,
contactName, r.getName());
} else {
return ctx.getString(R.string.introduction_request_received,
contactName, r.getName());
}
} else if (r instanceof ForumInvitationRequest) {
return ctx.getString(R.string.forum_invitation_received,
contactName, r.getName());
} else if (r instanceof BlogInvitationRequest) {
return ctx.getString(R.string.blogs_sharing_invitation_received,
contactName, r.getName());
} else if (r instanceof GroupInvitationRequest) {
return ctx.getString(
R.string.groups_invitations_invitation_received,
contactName, r.getName());
}
throw new IllegalArgumentException("Unknown PrivateRequest");
}
private static RequestType getType(PrivateRequest r) {
if (r instanceof IntroductionRequest) {
return INTRODUCTION;
} else if (r instanceof ForumInvitationRequest) {
return FORUM;
} else if (r instanceof BlogInvitationRequest) {
return BLOG;
} else if (r instanceof GroupInvitationRequest) {
return GROUP;
}
throw new IllegalArgumentException("Unknown PrivateRequest");
}
}
......@@ -84,11 +84,10 @@ class ForumControllerImpl extends
} else if (e instanceof ForumInvitationResponseReceivedEvent) {
ForumInvitationResponseReceivedEvent f =
(ForumInvitationResponseReceivedEvent) e;
ForumInvitationResponse r =
(ForumInvitationResponse) f.getResponse();
ForumInvitationResponse r = f.getMessageHeader();
if (r.getShareableId().equals(getGroupId()) && r.wasAccepted()) {
LOG.info("Forum invitation was accepted");
onForumInvitationAccepted(r.getContactId());
onForumInvitationAccepted(f.getContactId());
}
} else if (e instanceof ContactLeftShareableEvent) {
ContactLeftShareableEvent c = (ContactLeftShareableEvent) e;
......
......@@ -99,11 +99,10 @@ class GroupControllerImpl extends
} else if (e instanceof GroupInvitationResponseReceivedEvent) {
GroupInvitationResponseReceivedEvent g =
(GroupInvitationResponseReceivedEvent) e;
GroupInvitationResponse r =
(GroupInvitationResponse) g.getResponse();
GroupInvitationResponse r = g.getMessageHeader();
if (getGroupId().equals(r.getShareableId()) && r.wasAccepted()) {
listener.runOnUiThreadUnlessDestroyed(
() -> listener.onInvitationAccepted(r.getContactId()));
() -> listener.onInvitationAccepted(g.getContactId()));
}
} else if (e instanceof GroupDissolvedEvent) {
GroupDissolvedEvent g = (GroupDissolvedEvent) e;
......
/**
* Copyright (C) 2014 Open Whisper Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.thoughtcrime.securesms.components.util;
public interface FutureTaskListener<V> {
void onSuccess(V result);
void onFailure(Throwable error);
}
/*
* Copyright (C) 2014 Open Whisper Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.thoughtcrime.securesms.components.util;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import javax.annotation.Nullable;
public class ListenableFutureTask<V> extends FutureTask<V> {
private final List<FutureTaskListener<V>> listeners = new LinkedList<>();
@Nullable
private final Object identifier;
public ListenableFutureTask(Callable<V> callable) {
this(callable, null);
}
private ListenableFutureTask(Callable<V> callable,
@Nullable Object identifier) {
super(callable);
this.identifier = identifier;
}
public ListenableFutureTask(V result) {
this(result, null);
}
private ListenableFutureTask(V result, @Nullable Object identifier) {
super(() -> result);
this.identifier = identifier;
this.run();
}
public synchronized void addListener(FutureTaskListener<V> listener) {
if (this.isDone()) {
callback(listener);
} else {
this.listeners.add(listener);
}
}
public synchronized void removeListener(FutureTaskListener<V> listener) {
this.listeners.remove(listener);
}
@Override
protected synchronized void done() {
callback();
}
private void callback() {
for (FutureTaskListener<V> listener : listeners) {
callback(listener);
}
}
private void callback(FutureTaskListener<V> listener) {
if (listener != null) {
try {
listener.onSuccess(get());
} catch (InterruptedException e) {
throw new AssertionError(e);
} catch (ExecutionException e) {
listener.onFailure(e);
}
}
}
@Override
public boolean equals(Object other) {
if (other != null && other instanceof ListenableFutureTask &&
this.identifier != null) {
return identifier.equals(other);
} else {
return super.equals(other);
}
}
@Override
public int hashCode() {
if (<