From 64b596d0f9af182be3533685e223d9319563c176 Mon Sep 17 00:00:00 2001
From: Torsten Grote <t@grobox.de>
Date: Thu, 28 Jul 2016 19:10:59 -0300
Subject: [PATCH] Show Responses to Forum Invitations in Private Conversation

Closes #472
---
 .../ForumSharingIntegrationTest.java          | 93 ++++++++++++-------
 briar-android/res/values/strings.xml          |  4 +
 .../android/contact/ContactListFragment.java  | 22 ++++-
 .../android/contact/ConversationActivity.java | 30 ++++--
 .../android/contact/ConversationAdapter.java  |  4 +-
 .../ConversationForumInvitationInItem.java    |  4 +-
 .../ConversationForumInvitationItem.java      |  8 +-
 .../ConversationForumInvitationOutItem.java   |  4 +-
 .../android/contact/ConversationItem.java     | 41 +++++++-
 ...essage.java => BlogInvitationRequest.java} |  5 +-
 .../api/blogs/BlogSharingManager.java         |  4 +-
 ...ssage.java => ForumInvitationRequest.java} |  7 +-
 .../api/forum/ForumInvitationResponse.java    | 17 ++++
 .../api/forum/ForumSharingManager.java        |  5 +-
 .../api/sharing/InvitationMessage.java        | 15 +--
 .../api/sharing/InvitationRequest.java        | 30 ++++++
 .../api/sharing/InvitationResponse.java       | 22 +++++
 .../api/sharing/SharingMessage.java           |  1 -
 .../sharing/BlogSharingManagerImpl.java       | 31 ++++---
 .../sharing/ForumSharerSessionState.java      |  8 +-
 .../sharing/ForumSharingManagerImpl.java      | 33 ++++---
 .../briarproject/sharing/SharerEngine.java    |  2 +-
 .../sharing/SharingManagerImpl.java           | 60 ++++++++----
 23 files changed, 318 insertions(+), 132 deletions(-)
 rename briar-api/src/org/briarproject/api/blogs/{BlogInvitationMessage.java => BlogInvitationRequest.java} (76%)
 rename briar-api/src/org/briarproject/api/forum/{ForumInvitationMessage.java => ForumInvitationRequest.java} (70%)
 create mode 100644 briar-api/src/org/briarproject/api/forum/ForumInvitationResponse.java
 create mode 100644 briar-api/src/org/briarproject/api/sharing/InvitationRequest.java
 create mode 100644 briar-api/src/org/briarproject/api/sharing/InvitationResponse.java

diff --git a/briar-android-tests/src/test/java/org/briarproject/ForumSharingIntegrationTest.java b/briar-android-tests/src/test/java/org/briarproject/ForumSharingIntegrationTest.java
index 444f2f4c8d..2221f635b4 100644
--- a/briar-android-tests/src/test/java/org/briarproject/ForumSharingIntegrationTest.java
+++ b/briar-android-tests/src/test/java/org/briarproject/ForumSharingIntegrationTest.java
@@ -25,7 +25,8 @@ import org.briarproject.api.event.ForumInvitationReceivedEvent;
 import org.briarproject.api.event.ForumInvitationResponseReceivedEvent;
 import org.briarproject.api.event.MessageStateChangedEvent;
 import org.briarproject.api.forum.Forum;
-import org.briarproject.api.forum.ForumInvitationMessage;
+import org.briarproject.api.forum.ForumInvitationRequest;
+import org.briarproject.api.forum.ForumInvitationResponse;
 import org.briarproject.api.forum.ForumManager;
 import org.briarproject.api.forum.ForumPost;
 import org.briarproject.api.forum.ForumPostFactory;
@@ -35,6 +36,7 @@ import org.briarproject.api.identity.AuthorFactory;
 import org.briarproject.api.identity.IdentityManager;
 import org.briarproject.api.identity.LocalAuthor;
 import org.briarproject.api.lifecycle.LifecycleManager;
+import org.briarproject.api.sharing.InvitationMessage;
 import org.briarproject.api.sync.ClientId;
 import org.briarproject.api.sync.Group;
 import org.briarproject.api.sync.SyncSession;
@@ -187,18 +189,29 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
 			assertEquals(1, forumManager1.getForums().size());
 
 			// invitee has one invitation message from sharer
-			List<ForumInvitationMessage> list =
+			List<InvitationMessage> list =
 					new ArrayList<>(forumSharingManager1
 							.getInvitationMessages(contactId0));
-			assertEquals(1, list.size());
+			assertEquals(2, list.size());
 			// check other things are alright with the forum message
-			ForumInvitationMessage invitation = list.get(0);
-			assertFalse(invitation.isAvailable());
-			assertEquals(forum0.getName(), invitation.getForumName());
-			assertEquals(contactId1, invitation.getContactId());
-			assertEquals("Hi!", invitation.getMessage());
-			// sharer has own invitation message
-			assertEquals(1,
+			for (InvitationMessage m : list) {
+				if (m instanceof ForumInvitationRequest) {
+					ForumInvitationRequest invitation =
+							(ForumInvitationRequest) m;
+					assertFalse(invitation.isAvailable());
+					assertEquals(forum0.getName(), invitation.getForumName());
+					assertEquals(contactId1, invitation.getContactId());
+					assertEquals("Hi!", invitation.getMessage());
+				} else {
+					ForumInvitationResponse response =
+							(ForumInvitationResponse) m;
+					assertEquals(contactId0, response.getContactId());
+					assertTrue(response.wasAccepted());
+					assertTrue(response.isLocal());
+				}
+			}
+			// sharer has own invitation message and response
+			assertEquals(2,
 					forumSharingManager0.getInvitationMessages(contactId1)
 							.size());
 			// forum can not be shared again
@@ -238,19 +251,30 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
 			// forum is no longer available to invitee who declined
 			assertEquals(0, forumSharingManager1.getInvited().size());
 
-			// invitee has one invitation message from sharer
-			List<ForumInvitationMessage> list =
+			// invitee has one invitation message from sharer and one response
+			List<InvitationMessage> list =
 					new ArrayList<>(forumSharingManager1
 							.getInvitationMessages(contactId0));
-			assertEquals(1, list.size());
-			// check other things are alright with the forum message
-			ForumInvitationMessage invitation = list.get(0);
-			assertFalse(invitation.isAvailable());
-			assertEquals(forum0.getName(), invitation.getForumName());
-			assertEquals(contactId1, invitation.getContactId());
-			assertEquals(null, invitation.getMessage());
-			// sharer has own invitation message
-			assertEquals(1,
+			assertEquals(2, list.size());
+			// check things are alright with the forum message
+			for (InvitationMessage m : list) {
+				if (m instanceof ForumInvitationRequest) {
+					ForumInvitationRequest invitation =
+							(ForumInvitationRequest) m;
+					assertFalse(invitation.isAvailable());
+					assertEquals(forum0.getName(), invitation.getForumName());
+					assertEquals(contactId1, invitation.getContactId());
+					assertEquals(null, invitation.getMessage());
+				} else {
+					ForumInvitationResponse response =
+							(ForumInvitationResponse) m;
+					assertEquals(contactId0, response.getContactId());
+					assertFalse(response.wasAccepted());
+					assertTrue(response.isLocal());
+				}
+			}
+			// sharer has own invitation message and response
+			assertEquals(2,
 					forumSharingManager0.getInvitationMessages(contactId1)
 							.size());
 			// forum can be shared again
@@ -438,12 +462,13 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
 			listener1.requestReceived = false;
 
 			// get SessionId from invitation
-			List<ForumInvitationMessage> list = new ArrayList<>(
+			List<InvitationMessage> list = new ArrayList<>(
 					forumSharingManager1
 							.getInvitationMessages(contactId0));
-			assertEquals(1, list.size());
-			ForumInvitationMessage msg = list.get(0);
+			assertEquals(2, list.size());
+			InvitationMessage msg = list.get(0);
 			SessionId sessionId = msg.getSessionId();
+			assertEquals(sessionId, list.get(1).getSessionId());
 
 			// get all sorts of stuff needed to send a message
 			DatabaseComponent db = t0.getDatabaseComponent();
@@ -501,6 +526,9 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
 
 			// forum was added successfully
 			assertEquals(1, forumManager1.getForums().size());
+			assertEquals(2,
+					forumSharingManager0.getInvitationMessages(contactId1)
+							.size());
 
 			// invitee now shares same forum back
 			forumSharingManager1.sendInvitation(forum0.getId(),
@@ -512,7 +540,7 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
 
 			// make sure that no new request was received
 			assertFalse(listener0.requestReceived);
-			assertEquals(1,
+			assertEquals(2,
 					forumSharingManager0.getInvitationMessages(contactId1)
 							.size());
 		} finally {
@@ -566,9 +594,9 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
 				eventWaiter.await(TIMEOUT, 1);
 				assertTrue(listener0.responseReceived);
 
-				assertEquals(1, forumSharingManager0
+				assertEquals(2, forumSharingManager0
 						.getInvitationMessages(contactId1).size());
-				assertEquals(2, forumSharingManager1
+				assertEquals(3, forumSharingManager1
 						.getInvitationMessages(contactId0).size());
 			} else {
 				eventWaiter.await(TIMEOUT, 1);
@@ -579,9 +607,9 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
 				eventWaiter.await(TIMEOUT, 1);
 				assertTrue(listener1.responseReceived);
 
-				assertEquals(2, forumSharingManager0
+				assertEquals(3, forumSharingManager0
 						.getInvitationMessages(contactId1).size());
-				assertEquals(1, forumSharingManager1
+				assertEquals(2, forumSharingManager1
 						.getInvitationMessages(contactId0).size());
 			}
 		} finally {
@@ -616,12 +644,13 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
 					forumSharingManager0.getSharedWith(forum0.getId()).size());
 
 			// remember SessionId from invitation
-			List<ForumInvitationMessage> list = new ArrayList<>(
+			List<InvitationMessage> list = new ArrayList<>(
 					forumSharingManager1
 							.getInvitationMessages(contactId0));
-			assertEquals(1, list.size());
-			ForumInvitationMessage msg = list.get(0);
+			assertEquals(2, list.size());
+			InvitationMessage msg = list.get(0);
 			SessionId sessionId = msg.getSessionId();
+			assertEquals(sessionId, list.get(1).getSessionId());
 
 			// contacts now remove each other
 			contactManager0.removeContact(contactId1);
diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml
index 3c2084bd75..646f277780 100644
--- a/briar-android/res/values/strings.xml
+++ b/briar-android/res/values/strings.xml
@@ -222,6 +222,10 @@
 	<string name="forum_new_message_hint">New Entry</string>
 	<string name="forum_message_reply_hint">New Reply</string>
 	<string name="forum_invitation_already_sharing">Already sharing</string>
+	<string name="forum_invitation_response_accepted_sent">You accepted the forum invitation from %s.</string>
+	<string name="forum_invitation_response_declined_sent">You declined the forum invitation from %s.</string>
+	<string name="forum_invitation_response_accepted_received">%s accepted the forum invitation.</string>
+	<string name="forum_invitation_response_declined_received">%s declined the forum invitation.</string>
 
 	<!-- Dialogs -->
 	<string name="dialog_title_lost_password">Lost Password</string>
diff --git a/briar-android/src/org/briarproject/android/contact/ContactListFragment.java b/briar-android/src/org/briarproject/android/contact/ContactListFragment.java
index e113a9a085..27618e422d 100644
--- a/briar-android/src/org/briarproject/android/contact/ContactListFragment.java
+++ b/briar-android/src/org/briarproject/android/contact/ContactListFragment.java
@@ -34,10 +34,12 @@ import org.briarproject.api.event.Event;
 import org.briarproject.api.event.EventBus;
 import org.briarproject.api.event.EventListener;
 import org.briarproject.api.event.ForumInvitationReceivedEvent;
+import org.briarproject.api.event.ForumInvitationResponseReceivedEvent;
 import org.briarproject.api.event.IntroductionRequestReceivedEvent;
 import org.briarproject.api.event.IntroductionResponseReceivedEvent;
 import org.briarproject.api.event.PrivateMessageReceivedEvent;
-import org.briarproject.api.forum.ForumInvitationMessage;
+import org.briarproject.api.forum.ForumInvitationRequest;
+import org.briarproject.api.forum.ForumInvitationResponse;
 import org.briarproject.api.forum.ForumSharingManager;
 import org.briarproject.api.identity.IdentityManager;
 import org.briarproject.api.identity.LocalAuthor;
@@ -48,6 +50,7 @@ import org.briarproject.api.introduction.IntroductionResponse;
 import org.briarproject.api.messaging.MessagingManager;
 import org.briarproject.api.messaging.PrivateMessageHeader;
 import org.briarproject.api.plugins.ConnectionRegistry;
+import org.briarproject.api.sharing.InvitationMessage;
 import org.briarproject.api.sync.GroupId;
 
 import java.util.ArrayList;
@@ -277,6 +280,11 @@ public class ContactListFragment extends BaseFragment implements EventListener {
 			LOG.info("Forum Invitation received, reloading conversation...");
 			ForumInvitationReceivedEvent m = (ForumInvitationReceivedEvent) e;
 			reloadConversation(m.getContactId());
+		} else if (e instanceof ForumInvitationResponseReceivedEvent) {
+			LOG.info("Forum Invitation Response received, reloading ...");
+			ForumInvitationResponseReceivedEvent m =
+					(ForumInvitationResponseReceivedEvent) e;
+			reloadConversation(m.getContactId());
 		}
 	}
 
@@ -394,10 +402,16 @@ public class ContactListFragment extends BaseFragment implements EventListener {
 			LOG.info("Loading introduction messages took " + duration + " ms");
 
 		now = System.currentTimeMillis();
-		Collection<ForumInvitationMessage> invitations =
+		Collection<InvitationMessage> invitations =
 				forumSharingManager.getInvitationMessages(id);
-		for (ForumInvitationMessage i : invitations) {
-			messages.add(ConversationItem.from(i));
+		for (InvitationMessage i : invitations) {
+			if (i instanceof ForumInvitationRequest) {
+				ForumInvitationRequest r = (ForumInvitationRequest) i;
+				messages.add(ConversationItem.from(r));
+			} else if (i instanceof ForumInvitationResponse) {
+				ForumInvitationResponse r = (ForumInvitationResponse) i;
+				messages.add(ConversationItem.from(getActivity(), "", r));
+			}
 		}
 		duration = System.currentTimeMillis() - now;
 		if (LOG.isLoggable(INFO))
diff --git a/briar-android/src/org/briarproject/android/contact/ConversationActivity.java b/briar-android/src/org/briarproject/android/contact/ConversationActivity.java
index c85e84d8c4..a2dad23f42 100644
--- a/briar-android/src/org/briarproject/android/contact/ConversationActivity.java
+++ b/briar-android/src/org/briarproject/android/contact/ConversationActivity.java
@@ -45,12 +45,14 @@ import org.briarproject.api.event.Event;
 import org.briarproject.api.event.EventBus;
 import org.briarproject.api.event.EventListener;
 import org.briarproject.api.event.ForumInvitationReceivedEvent;
+import org.briarproject.api.event.ForumInvitationResponseReceivedEvent;
 import org.briarproject.api.event.IntroductionRequestReceivedEvent;
 import org.briarproject.api.event.IntroductionResponseReceivedEvent;
 import org.briarproject.api.event.MessagesAckedEvent;
 import org.briarproject.api.event.MessagesSentEvent;
 import org.briarproject.api.event.PrivateMessageReceivedEvent;
-import org.briarproject.api.forum.ForumInvitationMessage;
+import org.briarproject.api.forum.ForumInvitationRequest;
+import org.briarproject.api.forum.ForumInvitationResponse;
 import org.briarproject.api.forum.ForumSharingManager;
 import org.briarproject.api.introduction.IntroductionManager;
 import org.briarproject.api.introduction.IntroductionMessage;
@@ -61,6 +63,7 @@ import org.briarproject.api.messaging.PrivateMessage;
 import org.briarproject.api.messaging.PrivateMessageFactory;
 import org.briarproject.api.messaging.PrivateMessageHeader;
 import org.briarproject.api.plugins.ConnectionRegistry;
+import org.briarproject.api.sharing.InvitationMessage;
 import org.briarproject.api.sync.GroupId;
 import org.briarproject.api.sync.MessageId;
 import org.briarproject.util.StringUtils;
@@ -330,7 +333,7 @@ public class ConversationActivity extends BriarActivity
 					Collection<IntroductionMessage> introductions =
 							introductionManager
 									.getIntroductionMessages(contactId);
-					Collection<ForumInvitationMessage> invitations =
+					Collection<InvitationMessage> invitations =
 							forumSharingManager
 									.getInvitationMessages(contactId);
 					long duration = System.currentTimeMillis() - now;
@@ -349,7 +352,7 @@ public class ConversationActivity extends BriarActivity
 
 	private void displayMessages(final Collection<PrivateMessageHeader> headers,
 			final Collection<IntroductionMessage> introductions,
-			final Collection<ForumInvitationMessage> invitations) {
+			final Collection<InvitationMessage> invitations) {
 		runOnUiThread(new Runnable() {
 			@Override
 			public void run() {
@@ -383,9 +386,18 @@ public class ConversationActivity extends BriarActivity
 						}
 						items.add(item);
 					}
-					for (ForumInvitationMessage i : invitations) {
-						ConversationItem item = ConversationItem.from(i);
-						items.add(item);
+					for (InvitationMessage i : invitations) {
+						if (i instanceof ForumInvitationRequest) {
+							ForumInvitationRequest r =
+									(ForumInvitationRequest) i;
+							items.add(ConversationItem.from(r));
+						} else if (i instanceof ForumInvitationResponse) {
+							ForumInvitationResponse r =
+									(ForumInvitationResponse) i;
+							items.add(ConversationItem
+									.from(ConversationActivity.this,
+											contactName, r));
+						}
 					}
 					adapter.addAll(items);
 					// Scroll to the bottom
@@ -547,6 +559,12 @@ public class ConversationActivity extends BriarActivity
 			if (event.getContactId().equals(contactId)) {
 				loadMessages();
 			}
+		} else if (e instanceof ForumInvitationResponseReceivedEvent) {
+			ForumInvitationResponseReceivedEvent event =
+					(ForumInvitationResponseReceivedEvent) e;
+			if (event.getContactId().equals(contactId)) {
+				loadMessages();
+			}
 		}
 	}
 
diff --git a/briar-android/src/org/briarproject/android/contact/ConversationAdapter.java b/briar-android/src/org/briarproject/android/contact/ConversationAdapter.java
index 2884350ea9..15b9059089 100644
--- a/briar-android/src/org/briarproject/android/contact/ConversationAdapter.java
+++ b/briar-android/src/org/briarproject/android/contact/ConversationAdapter.java
@@ -16,7 +16,7 @@ import org.briarproject.R;
 import org.briarproject.android.forum.ForumInvitationsActivity;
 import org.briarproject.android.util.AndroidUtils;
 import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.forum.ForumInvitationMessage;
+import org.briarproject.api.forum.ForumInvitationRequest;
 import org.briarproject.api.introduction.IntroductionRequest;
 import org.briarproject.api.messaging.PrivateMessageHeader;
 import org.briarproject.util.StringUtils;
@@ -278,7 +278,7 @@ class ConversationAdapter extends RecyclerView.Adapter {
 	private void bindInvitation(InvitationHolder ui,
 			final ConversationForumInvitationItem item) {
 
-		ForumInvitationMessage fim = item.getForumInvitationMessage();
+		ForumInvitationRequest fim = item.getForumInvitationMessage();
 
 		String message = fim.getMessage();
 		if (StringUtils.isNullOrEmpty(message)) {
diff --git a/briar-android/src/org/briarproject/android/contact/ConversationForumInvitationInItem.java b/briar-android/src/org/briarproject/android/contact/ConversationForumInvitationInItem.java
index b082fe4d6a..bfa5da5457 100644
--- a/briar-android/src/org/briarproject/android/contact/ConversationForumInvitationInItem.java
+++ b/briar-android/src/org/briarproject/android/contact/ConversationForumInvitationInItem.java
@@ -1,6 +1,6 @@
 package org.briarproject.android.contact;
 
-import org.briarproject.api.forum.ForumInvitationMessage;
+import org.briarproject.api.forum.ForumInvitationRequest;
 
 // This class is not thread-safe
 public class ConversationForumInvitationInItem
@@ -9,7 +9,7 @@ public class ConversationForumInvitationInItem
 
 	private boolean read;
 
-	public ConversationForumInvitationInItem(ForumInvitationMessage fim) {
+	public ConversationForumInvitationInItem(ForumInvitationRequest fim) {
 		super(fim);
 
 		this.read = fim.isRead();
diff --git a/briar-android/src/org/briarproject/android/contact/ConversationForumInvitationItem.java b/briar-android/src/org/briarproject/android/contact/ConversationForumInvitationItem.java
index eb303d16b5..50c5c64d2c 100644
--- a/briar-android/src/org/briarproject/android/contact/ConversationForumInvitationItem.java
+++ b/briar-android/src/org/briarproject/android/contact/ConversationForumInvitationItem.java
@@ -1,18 +1,18 @@
 package org.briarproject.android.contact;
 
-import org.briarproject.api.forum.ForumInvitationMessage;
+import org.briarproject.api.forum.ForumInvitationRequest;
 
 abstract class ConversationForumInvitationItem extends ConversationItem {
 
-	private final ForumInvitationMessage fim;
+	private final ForumInvitationRequest fim;
 
-	public ConversationForumInvitationItem(ForumInvitationMessage fim) {
+	public ConversationForumInvitationItem(ForumInvitationRequest fim) {
 		super(fim.getId(), fim.getTimestamp());
 
 		this.fim = fim;
 	}
 
-	public ForumInvitationMessage getForumInvitationMessage() {
+	public ForumInvitationRequest getForumInvitationMessage() {
 		return fim;
 	}
 }
diff --git a/briar-android/src/org/briarproject/android/contact/ConversationForumInvitationOutItem.java b/briar-android/src/org/briarproject/android/contact/ConversationForumInvitationOutItem.java
index 202023dda2..5551fa60c5 100644
--- a/briar-android/src/org/briarproject/android/contact/ConversationForumInvitationOutItem.java
+++ b/briar-android/src/org/briarproject/android/contact/ConversationForumInvitationOutItem.java
@@ -1,6 +1,6 @@
 package org.briarproject.android.contact;
 
-import org.briarproject.api.forum.ForumInvitationMessage;
+import org.briarproject.api.forum.ForumInvitationRequest;
 
 /**
  * This class is needed and can not be replaced by an ConversationNoticeOutItem,
@@ -15,7 +15,7 @@ public class ConversationForumInvitationOutItem
 
 	private boolean sent, seen;
 
-	public ConversationForumInvitationOutItem(ForumInvitationMessage fim) {
+	public ConversationForumInvitationOutItem(ForumInvitationRequest fim) {
 		super(fim);
 		this.sent = fim.isSent();
 		this.seen = fim.isSeen();
diff --git a/briar-android/src/org/briarproject/android/contact/ConversationItem.java b/briar-android/src/org/briarproject/android/contact/ConversationItem.java
index 7b75cb13a6..18cfbd742a 100644
--- a/briar-android/src/org/briarproject/android/contact/ConversationItem.java
+++ b/briar-android/src/org/briarproject/android/contact/ConversationItem.java
@@ -3,7 +3,8 @@ package org.briarproject.android.contact;
 import android.content.Context;
 
 import org.briarproject.R;
-import org.briarproject.api.forum.ForumInvitationMessage;
+import org.briarproject.api.forum.ForumInvitationRequest;
+import org.briarproject.api.forum.ForumInvitationResponse;
 import org.briarproject.api.introduction.IntroductionMessage;
 import org.briarproject.api.introduction.IntroductionRequest;
 import org.briarproject.api.introduction.IntroductionResponse;
@@ -95,7 +96,7 @@ public abstract class ConversationItem {
 		}
 	}
 
-	public static ConversationItem from(ForumInvitationMessage fim) {
+	public static ConversationItem from(ForumInvitationRequest fim) {
 		if (fim.isLocal()) {
 			return new ConversationForumInvitationOutItem(fim);
 		} else {
@@ -103,6 +104,38 @@ public abstract class ConversationItem {
 		}
 	}
 
+	public static ConversationItem from(Context ctx, String contactName,
+			ForumInvitationResponse fir) {
+
+		if (fir.isLocal()) {
+			String text;
+			if (fir.wasAccepted()) {
+				text = ctx.getString(
+						R.string.forum_invitation_response_accepted_sent,
+						contactName);
+			} else {
+				text = ctx.getString(
+						R.string.forum_invitation_response_declined_sent,
+						contactName);
+			}
+			return new ConversationNoticeOutItem(fir.getId(), text,
+					fir.getTimestamp(), fir.isSent(), fir.isSeen());
+		} else {
+			String text;
+			if (fir.wasAccepted()) {
+				text = ctx.getString(
+						R.string.forum_invitation_response_accepted_received,
+						contactName);
+			} else {
+				text = ctx.getString(
+						R.string.forum_invitation_response_declined_received,
+						contactName);
+			}
+			return new ConversationNoticeInItem(fir.getId(), text,
+					fir.getTimestamp(), fir.isRead());
+		}
+	}
+
 	/**
 	 * This method should not be used to get user-facing objects,
 	 * Its purpose is to provider data for the contact list.
@@ -115,7 +148,7 @@ public abstract class ConversationItem {
 				im.getTimestamp(), im.isRead());
 	}
 
-	protected interface OutgoingItem {
+	interface OutgoingItem {
 
 		MessageId getId();
 
@@ -128,7 +161,7 @@ public abstract class ConversationItem {
 		void setSeen(boolean seen);
 	}
 
-	protected interface IncomingItem {
+	interface IncomingItem {
 
 		MessageId getId();
 
diff --git a/briar-api/src/org/briarproject/api/blogs/BlogInvitationMessage.java b/briar-api/src/org/briarproject/api/blogs/BlogInvitationRequest.java
similarity index 76%
rename from briar-api/src/org/briarproject/api/blogs/BlogInvitationMessage.java
rename to briar-api/src/org/briarproject/api/blogs/BlogInvitationRequest.java
index 9306da5726..473955960a 100644
--- a/briar-api/src/org/briarproject/api/blogs/BlogInvitationMessage.java
+++ b/briar-api/src/org/briarproject/api/blogs/BlogInvitationRequest.java
@@ -3,13 +3,14 @@ package org.briarproject.api.blogs;
 import org.briarproject.api.clients.SessionId;
 import org.briarproject.api.contact.ContactId;
 import org.briarproject.api.sharing.InvitationMessage;
+import org.briarproject.api.sharing.InvitationRequest;
 import org.briarproject.api.sync.MessageId;
 
-public class BlogInvitationMessage extends InvitationMessage {
+public class BlogInvitationRequest extends InvitationRequest {
 
 	private final String blogTitle;
 
-	public BlogInvitationMessage(MessageId id, SessionId sessionId,
+	public BlogInvitationRequest(MessageId id, SessionId sessionId,
 			ContactId contactId, String blogTitle, String message,
 			boolean available, long time, boolean local, boolean sent,
 			boolean seen, boolean read) {
diff --git a/briar-api/src/org/briarproject/api/blogs/BlogSharingManager.java b/briar-api/src/org/briarproject/api/blogs/BlogSharingManager.java
index 6fed69e19f..59e06c712f 100644
--- a/briar-api/src/org/briarproject/api/blogs/BlogSharingManager.java
+++ b/briar-api/src/org/briarproject/api/blogs/BlogSharingManager.java
@@ -10,7 +10,7 @@ import org.briarproject.api.sync.GroupId;
 import java.util.Collection;
 
 public interface BlogSharingManager
-		extends SharingManager<Blog, BlogInvitationMessage> {
+		extends SharingManager<Blog, BlogInvitationRequest> {
 
 	/**
 	 * Returns the unique ID of the blog sharing client.
@@ -34,7 +34,7 @@ public interface BlogSharingManager
 	 * Returns all blogs sharing messages sent by the Contact
 	 * identified by contactId.
 	 */
-	Collection<BlogInvitationMessage> getInvitationMessages(
+	Collection<BlogInvitationRequest> getInvitationMessages(
 			ContactId contactId) throws DbException;
 
 	/**
diff --git a/briar-api/src/org/briarproject/api/forum/ForumInvitationMessage.java b/briar-api/src/org/briarproject/api/forum/ForumInvitationRequest.java
similarity index 70%
rename from briar-api/src/org/briarproject/api/forum/ForumInvitationMessage.java
rename to briar-api/src/org/briarproject/api/forum/ForumInvitationRequest.java
index fd2d6b0d8c..f043ca2011 100644
--- a/briar-api/src/org/briarproject/api/forum/ForumInvitationMessage.java
+++ b/briar-api/src/org/briarproject/api/forum/ForumInvitationRequest.java
@@ -2,15 +2,14 @@ package org.briarproject.api.forum;
 
 import org.briarproject.api.clients.SessionId;
 import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.messaging.BaseMessage;
-import org.briarproject.api.sharing.InvitationMessage;
+import org.briarproject.api.sharing.InvitationRequest;
 import org.briarproject.api.sync.MessageId;
 
-public class ForumInvitationMessage extends InvitationMessage {
+public class ForumInvitationRequest extends InvitationRequest {
 
 	private final String forumName;
 
-	public ForumInvitationMessage(MessageId id, SessionId sessionId,
+	public ForumInvitationRequest(MessageId id, SessionId sessionId,
 			ContactId contactId, String forumName, String message,
 			boolean available, long time, boolean local, boolean sent,
 			boolean seen, boolean read) {
diff --git a/briar-api/src/org/briarproject/api/forum/ForumInvitationResponse.java b/briar-api/src/org/briarproject/api/forum/ForumInvitationResponse.java
new file mode 100644
index 0000000000..00a15eac2e
--- /dev/null
+++ b/briar-api/src/org/briarproject/api/forum/ForumInvitationResponse.java
@@ -0,0 +1,17 @@
+package org.briarproject.api.forum;
+
+import org.briarproject.api.clients.SessionId;
+import org.briarproject.api.contact.ContactId;
+import org.briarproject.api.sharing.InvitationResponse;
+import org.briarproject.api.sync.MessageId;
+
+public class ForumInvitationResponse extends InvitationResponse {
+
+	public ForumInvitationResponse(MessageId id, SessionId sessionId,
+			ContactId contactId, boolean accept, long time, boolean local,
+			boolean sent, boolean seen, boolean read) {
+
+		super(id, sessionId, contactId, accept, time, local, sent, seen, read);
+	}
+
+}
diff --git a/briar-api/src/org/briarproject/api/forum/ForumSharingManager.java b/briar-api/src/org/briarproject/api/forum/ForumSharingManager.java
index 365cf18e75..2ad3228dd9 100644
--- a/briar-api/src/org/briarproject/api/forum/ForumSharingManager.java
+++ b/briar-api/src/org/briarproject/api/forum/ForumSharingManager.java
@@ -3,13 +3,14 @@ package org.briarproject.api.forum;
 import org.briarproject.api.contact.Contact;
 import org.briarproject.api.contact.ContactId;
 import org.briarproject.api.db.DbException;
+import org.briarproject.api.sharing.InvitationMessage;
 import org.briarproject.api.sharing.SharingManager;
 import org.briarproject.api.sync.ClientId;
 import org.briarproject.api.sync.GroupId;
 
 import java.util.Collection;
 
-public interface ForumSharingManager extends SharingManager<Forum, ForumInvitationMessage> {
+public interface ForumSharingManager extends SharingManager<Forum, InvitationMessage> {
 
 	/** Returns the unique ID of the forum sharing client. */
 	ClientId getClientId();
@@ -31,7 +32,7 @@ public interface ForumSharingManager extends SharingManager<Forum, ForumInvitati
 	 * Returns all forum sharing messages sent by the Contact
 	 * identified by contactId.
 	 */
-	Collection<ForumInvitationMessage> getInvitationMessages(
+	Collection<InvitationMessage> getInvitationMessages(
 			ContactId contactId) throws DbException;
 
 	/** Returns all forums to which the user has been invited. */
diff --git a/briar-api/src/org/briarproject/api/sharing/InvitationMessage.java b/briar-api/src/org/briarproject/api/sharing/InvitationMessage.java
index 4d3c12e261..181a04059e 100644
--- a/briar-api/src/org/briarproject/api/sharing/InvitationMessage.java
+++ b/briar-api/src/org/briarproject/api/sharing/InvitationMessage.java
@@ -9,19 +9,14 @@ public abstract class InvitationMessage extends BaseMessage {
 
 	private final SessionId sessionId;
 	private final ContactId contactId;
-	private final String message;
-	private final boolean available;
 
 	public InvitationMessage(MessageId id, SessionId sessionId,
-			ContactId contactId, String message,
-			boolean available, long time, boolean local, boolean sent,
+			ContactId contactId, long time, boolean local, boolean sent,
 			boolean seen, boolean read) {
 
 		super(id, time, local, read, sent, seen);
 		this.sessionId = sessionId;
 		this.contactId = contactId;
-		this.message = message;
-		this.available = available;
 	}
 
 	public SessionId getSessionId() {
@@ -32,12 +27,4 @@ public abstract class InvitationMessage extends BaseMessage {
 		return contactId;
 	}
 
-	public String getMessage() {
-		return message;
-	}
-
-	public boolean isAvailable() {
-		return available;
-	}
-
 }
diff --git a/briar-api/src/org/briarproject/api/sharing/InvitationRequest.java b/briar-api/src/org/briarproject/api/sharing/InvitationRequest.java
new file mode 100644
index 0000000000..6d5f07d35e
--- /dev/null
+++ b/briar-api/src/org/briarproject/api/sharing/InvitationRequest.java
@@ -0,0 +1,30 @@
+package org.briarproject.api.sharing;
+
+import org.briarproject.api.clients.SessionId;
+import org.briarproject.api.contact.ContactId;
+import org.briarproject.api.sync.MessageId;
+
+public abstract class InvitationRequest extends InvitationMessage {
+
+	private final String message;
+	private final boolean available;
+
+	public InvitationRequest(MessageId id, SessionId sessionId,
+			ContactId contactId, String message,
+			boolean available, long time, boolean local, boolean sent,
+			boolean seen, boolean read) {
+
+		super(id, sessionId, contactId, time, local, read, sent, seen);
+		this.message = message;
+		this.available = available;
+	}
+
+	public String getMessage() {
+		return message;
+	}
+
+	public boolean isAvailable() {
+		return available;
+	}
+
+}
diff --git a/briar-api/src/org/briarproject/api/sharing/InvitationResponse.java b/briar-api/src/org/briarproject/api/sharing/InvitationResponse.java
new file mode 100644
index 0000000000..cf4d53774e
--- /dev/null
+++ b/briar-api/src/org/briarproject/api/sharing/InvitationResponse.java
@@ -0,0 +1,22 @@
+package org.briarproject.api.sharing;
+
+import org.briarproject.api.clients.SessionId;
+import org.briarproject.api.contact.ContactId;
+import org.briarproject.api.sync.MessageId;
+
+public abstract class InvitationResponse extends InvitationMessage {
+
+	private final boolean accept;
+
+	public InvitationResponse(MessageId id, SessionId sessionId,
+			ContactId contactId, boolean accept, long time, boolean local,
+			boolean sent, boolean seen, boolean read) {
+
+		super(id, sessionId, contactId, time, local, read, sent, seen);
+		this.accept = accept;
+	}
+
+	public boolean wasAccepted() {
+		return accept;
+	}
+}
diff --git a/briar-api/src/org/briarproject/api/sharing/SharingMessage.java b/briar-api/src/org/briarproject/api/sharing/SharingMessage.java
index 2b14cefde4..be0cac328d 100644
--- a/briar-api/src/org/briarproject/api/sharing/SharingMessage.java
+++ b/briar-api/src/org/briarproject/api/sharing/SharingMessage.java
@@ -23,7 +23,6 @@ public interface SharingMessage {
 		private final SessionId sessionId;
 
 		BaseMessage(GroupId groupId, SessionId sessionId) {
-
 			this.groupId = groupId;
 			this.sessionId = sessionId;
 		}
diff --git a/briar-core/src/org/briarproject/sharing/BlogSharingManagerImpl.java b/briar-core/src/org/briarproject/sharing/BlogSharingManagerImpl.java
index a8bd64b2aa..5632ea9940 100644
--- a/briar-core/src/org/briarproject/sharing/BlogSharingManagerImpl.java
+++ b/briar-core/src/org/briarproject/sharing/BlogSharingManagerImpl.java
@@ -3,7 +3,7 @@ package org.briarproject.sharing;
 import org.briarproject.api.FormatException;
 import org.briarproject.api.blogs.Blog;
 import org.briarproject.api.blogs.BlogFactory;
-import org.briarproject.api.blogs.BlogInvitationMessage;
+import org.briarproject.api.blogs.BlogInvitationRequest;
 import org.briarproject.api.blogs.BlogManager;
 import org.briarproject.api.blogs.BlogManager.RemoveBlogHook;
 import org.briarproject.api.blogs.BlogSharingManager;
@@ -40,15 +40,13 @@ import static org.briarproject.api.blogs.BlogConstants.BLOG_PUBLIC_KEY;
 import static org.briarproject.api.blogs.BlogConstants.BLOG_TITLE;
 
 class BlogSharingManagerImpl extends
-		SharingManagerImpl<Blog, BlogInvitation, BlogInvitationMessage, BlogInviteeSessionState, BlogSharerSessionState, BlogInvitationReceivedEvent, BlogInvitationResponseReceivedEvent>
+		SharingManagerImpl<Blog, BlogInvitation, BlogInvitationRequest, BlogInviteeSessionState, BlogSharerSessionState, BlogInvitationReceivedEvent, BlogInvitationResponseReceivedEvent>
 		implements BlogSharingManager, RemoveBlogHook {
 
 	static final ClientId CLIENT_ID = new ClientId(StringUtils.fromHexString(
 			"bee438b5de0b3a685badc4e49d76e72d"
 					+ "21e01c4b569a775112756bdae267a028"));
 
-	private final BlogManager blogManager;
-
 	private final SFactory sFactory;
 	private final IFactory iFactory;
 	private final ISFactory isFactory;
@@ -65,7 +63,6 @@ class BlogSharingManagerImpl extends
 
 		super(db, messageQueueManager, clientHelper, metadataParser,
 				metadataEncoder, random, privateGroupFactory, clock);
-		this.blogManager = blogManager;
 
 		sFactory = new SFactory(authorFactory, blogFactory, blogManager);
 		iFactory = new IFactory();
@@ -81,15 +78,23 @@ class BlogSharingManagerImpl extends
 	}
 
 	@Override
-	protected BlogInvitationMessage createInvitationMessage(MessageId id,
+	protected BlogInvitationRequest createInvitationRequest(MessageId id,
 			BlogInvitation msg, ContactId contactId, boolean available,
 			long time, boolean local, boolean sent, boolean seen,
 			boolean read) {
-		return new BlogInvitationMessage(id, msg.getSessionId(), contactId,
+		return new BlogInvitationRequest(id, msg.getSessionId(), contactId,
 				msg.getBlogTitle(), msg.getMessage(), available, time, local,
 				sent, seen, read);
 	}
 
+	@Override
+	protected BlogInvitationRequest createInvitationResponse(MessageId id,
+			SessionId sessionId, ContactId contactId, boolean accept, long time,
+			boolean local, boolean sent, boolean seen, boolean read) {
+		// TODO implement when doing blog sharing
+		return null;
+	}
+
 	@Override
 	protected ShareableFactory<Blog, BlogInvitation, BlogInviteeSessionState, BlogSharerSessionState> getSFactory() {
 		return sFactory;
@@ -125,7 +130,7 @@ class BlogSharingManagerImpl extends
 		removingShareable(txn, b);
 	}
 
-	static class SFactory implements
+	private static class SFactory implements
 			ShareableFactory<Blog, BlogInvitation, BlogInviteeSessionState, BlogSharerSessionState> {
 
 		private final AuthorFactory authorFactory;
@@ -190,7 +195,7 @@ class BlogSharingManagerImpl extends
 		}
 	}
 
-	static class IFactory implements
+	private static class IFactory implements
 			InvitationFactory<BlogInvitation, BlogSharerSessionState> {
 		@Override
 		public BlogInvitation build(GroupId groupId, BdfDictionary d)
@@ -207,7 +212,7 @@ class BlogSharingManagerImpl extends
 		}
 	}
 
-	static class ISFactory implements
+	private static class ISFactory implements
 			InviteeSessionStateFactory<Blog, BlogInviteeSessionState> {
 		@Override
 		public BlogInviteeSessionState build(SessionId sessionId,
@@ -235,7 +240,7 @@ class BlogSharingManagerImpl extends
 		}
 	}
 
-	static class SSFactory implements
+	private static class SSFactory implements
 			SharerSessionStateFactory<Blog, BlogSharerSessionState> {
 		@Override
 		public BlogSharerSessionState build(SessionId sessionId,
@@ -263,7 +268,7 @@ class BlogSharingManagerImpl extends
 		}
 	}
 
-	static class IRFactory implements
+	private static class IRFactory implements
 			InvitationReceivedEventFactory<BlogInviteeSessionState, BlogInvitationReceivedEvent> {
 
 		private final SFactory sFactory;
@@ -281,7 +286,7 @@ class BlogSharingManagerImpl extends
 		}
 	}
 
-	static class IRRFactory implements
+	private static class IRRFactory implements
 			InvitationResponseReceivedEventFactory<BlogSharerSessionState, BlogInvitationResponseReceivedEvent> {
 		@Override
 		public BlogInvitationResponseReceivedEvent build(
diff --git a/briar-core/src/org/briarproject/sharing/ForumSharerSessionState.java b/briar-core/src/org/briarproject/sharing/ForumSharerSessionState.java
index cfc0c231c7..4e0fd05049 100644
--- a/briar-core/src/org/briarproject/sharing/ForumSharerSessionState.java
+++ b/briar-core/src/org/briarproject/sharing/ForumSharerSessionState.java
@@ -9,12 +9,12 @@ import org.briarproject.api.sync.MessageId;
 import static org.briarproject.api.forum.ForumConstants.FORUM_NAME;
 import static org.briarproject.api.forum.ForumConstants.FORUM_SALT;
 
-public class ForumSharerSessionState extends SharerSessionState {
+class ForumSharerSessionState extends SharerSessionState {
 
 	private final String forumName;
 	private final byte[] forumSalt;
 
-	public ForumSharerSessionState(SessionId sessionId, MessageId storageId,
+	ForumSharerSessionState(SessionId sessionId, MessageId storageId,
 			GroupId groupId, State state, ContactId contactId, GroupId forumId,
 			String forumName, byte[] forumSalt) {
 		super(sessionId, storageId, groupId, state, contactId, forumId);
@@ -30,11 +30,11 @@ public class ForumSharerSessionState extends SharerSessionState {
 		return d;
 	}
 
-	public String getForumName() {
+	String getForumName() {
 		return forumName;
 	}
 
-	public byte[] getForumSalt() {
+	byte[] getForumSalt() {
 		return forumSalt;
 	}
 }
diff --git a/briar-core/src/org/briarproject/sharing/ForumSharingManagerImpl.java b/briar-core/src/org/briarproject/sharing/ForumSharingManagerImpl.java
index 9cee634636..95f9f0ef5e 100644
--- a/briar-core/src/org/briarproject/sharing/ForumSharingManagerImpl.java
+++ b/briar-core/src/org/briarproject/sharing/ForumSharingManagerImpl.java
@@ -17,10 +17,12 @@ import org.briarproject.api.event.ForumInvitationReceivedEvent;
 import org.briarproject.api.event.ForumInvitationResponseReceivedEvent;
 import org.briarproject.api.forum.Forum;
 import org.briarproject.api.forum.ForumFactory;
-import org.briarproject.api.forum.ForumInvitationMessage;
+import org.briarproject.api.forum.ForumInvitationRequest;
+import org.briarproject.api.forum.ForumInvitationResponse;
 import org.briarproject.api.forum.ForumManager;
 import org.briarproject.api.forum.ForumSharingManager;
 import org.briarproject.api.forum.ForumSharingMessage.ForumInvitation;
+import org.briarproject.api.sharing.InvitationMessage;
 import org.briarproject.api.sync.ClientId;
 import org.briarproject.api.sync.GroupId;
 import org.briarproject.api.sync.MessageId;
@@ -35,15 +37,13 @@ import static org.briarproject.api.forum.ForumConstants.FORUM_NAME;
 import static org.briarproject.api.forum.ForumConstants.FORUM_SALT;
 
 class ForumSharingManagerImpl extends
-		SharingManagerImpl<Forum, ForumInvitation, ForumInvitationMessage, ForumInviteeSessionState, ForumSharerSessionState, ForumInvitationReceivedEvent, ForumInvitationResponseReceivedEvent>
+		SharingManagerImpl<Forum, ForumInvitation, InvitationMessage, ForumInviteeSessionState, ForumSharerSessionState, ForumInvitationReceivedEvent, ForumInvitationResponseReceivedEvent>
 		implements ForumSharingManager, ForumManager.RemoveForumHook {
 
 	static final ClientId CLIENT_ID = new ClientId(StringUtils.fromHexString(
 			"cd11a5d04dccd9e2931d6fc3df456313"
 					+ "63bb3e9d9d0e9405fccdb051f41f5449"));
 
-	private final ForumManager forumManager;
-
 	private final SFactory sFactory;
 	private final IFactory iFactory;
 	private final ISFactory isFactory;
@@ -63,7 +63,6 @@ class ForumSharingManagerImpl extends
 			SecureRandom random) {
 		super(db, messageQueueManager, clientHelper, metadataParser,
 				metadataEncoder, random, privateGroupFactory, clock);
-		this.forumManager = forumManager;
 
 		sFactory = new SFactory(forumFactory, forumManager);
 		iFactory = new IFactory();
@@ -79,15 +78,23 @@ class ForumSharingManagerImpl extends
 	}
 
 	@Override
-	protected ForumInvitationMessage createInvitationMessage(MessageId id,
+	protected InvitationMessage createInvitationRequest(MessageId id,
 			ForumInvitation msg, ContactId contactId, boolean available,
 			long time, boolean local, boolean sent, boolean seen,
 			boolean read) {
-		return new ForumInvitationMessage(id, msg.getSessionId(), contactId,
+		return new ForumInvitationRequest(id, msg.getSessionId(), contactId,
 				msg.getForumName(), msg.getMessage(), available, time, local,
 				sent, seen, read);
 	}
 
+	@Override
+	protected InvitationMessage createInvitationResponse(MessageId id,
+			SessionId sessionId, ContactId contactId, boolean accept,
+			long time, boolean local, boolean sent, boolean seen, boolean read) {
+		return new ForumInvitationResponse(id, sessionId, contactId, accept,
+				time, local, sent, seen, read);
+	}
+
 	@Override
 	protected ShareableFactory<Forum, ForumInvitation, ForumInviteeSessionState, ForumSharerSessionState> getSFactory() {
 		return sFactory;
@@ -123,7 +130,7 @@ class ForumSharingManagerImpl extends
 		removingShareable(txn, f);
 	}
 
-	static class SFactory implements
+	private static class SFactory implements
 			ShareableFactory<Forum, ForumInvitation, ForumInviteeSessionState, ForumSharerSessionState> {
 
 		private final ForumFactory forumFactory;
@@ -169,7 +176,7 @@ class ForumSharingManagerImpl extends
 		}
 	}
 
-	static class IFactory implements
+	private static class IFactory implements
 			InvitationFactory<ForumInvitation, ForumSharerSessionState> {
 		@Override
 		public ForumInvitation build(GroupId groupId, BdfDictionary d)
@@ -185,7 +192,7 @@ class ForumSharingManagerImpl extends
 		}
 	}
 
-	static class ISFactory implements
+	private static class ISFactory implements
 			InviteeSessionStateFactory<Forum, ForumInviteeSessionState> {
 		@Override
 		public ForumInviteeSessionState build(SessionId sessionId,
@@ -209,7 +216,7 @@ class ForumSharingManagerImpl extends
 		}
 	}
 
-	static class SSFactory implements
+	private static class SSFactory implements
 			SharerSessionStateFactory<Forum, ForumSharerSessionState> {
 		@Override
 		public ForumSharerSessionState build(SessionId sessionId,
@@ -233,7 +240,7 @@ class ForumSharingManagerImpl extends
 		}
 	}
 
-	static class IRFactory implements
+	private static class IRFactory implements
 			InvitationReceivedEventFactory<ForumInviteeSessionState, ForumInvitationReceivedEvent> {
 
 		private final SFactory sFactory;
@@ -251,7 +258,7 @@ class ForumSharingManagerImpl extends
 		}
 	}
 
-	static class IRRFactory implements
+	private static class IRRFactory implements
 			InvitationResponseReceivedEventFactory<ForumSharerSessionState, ForumInvitationResponseReceivedEvent> {
 		@Override
 		public ForumInvitationResponseReceivedEvent build(
diff --git a/briar-core/src/org/briarproject/sharing/SharerEngine.java b/briar-core/src/org/briarproject/sharing/SharerEngine.java
index 7b09727c50..4f7d23f83b 100644
--- a/briar-core/src/org/briarproject/sharing/SharerEngine.java
+++ b/briar-core/src/org/briarproject/sharing/SharerEngine.java
@@ -23,7 +23,7 @@ import static org.briarproject.api.sharing.SharingMessage.BaseMessage;
 import static org.briarproject.api.sharing.SharingMessage.Invitation;
 import static org.briarproject.api.sharing.SharingMessage.SimpleMessage;
 
-public class SharerEngine<I extends Invitation, SS extends SharerSessionState, IRR extends InvitationResponseReceivedEvent>
+class SharerEngine<I extends Invitation, SS extends SharerSessionState, IRR extends InvitationResponseReceivedEvent>
 		implements ProtocolEngine<SharerSessionState.Action, SS, BaseMessage> {
 
 	private static final Logger LOG =
diff --git a/briar-core/src/org/briarproject/sharing/SharingManagerImpl.java b/briar-core/src/org/briarproject/sharing/SharingManagerImpl.java
index 9df89ceb6d..ce34826ec4 100644
--- a/briar-core/src/org/briarproject/sharing/SharingManagerImpl.java
+++ b/briar-core/src/org/briarproject/sharing/SharingManagerImpl.java
@@ -117,10 +117,14 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IM
 
 	public abstract ClientId getClientId();
 
-	protected abstract IM createInvitationMessage(MessageId id, I msg,
+	protected abstract IM createInvitationRequest(MessageId id, I msg,
 			ContactId contactId, boolean available, long time, boolean local,
 			boolean sent, boolean seen, boolean read);
 
+	protected abstract IM createInvitationResponse(MessageId id,
+			SessionId sessionId, ContactId contactId, boolean accept, long time,
+			boolean local, boolean sent, boolean seen, boolean read);
+
 	protected abstract ShareableFactory<S, I, IS, SS> getSFactory();
 
 	protected abstract InvitationFactory<I, SS> getIFactory();
@@ -325,11 +329,6 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IM
 	public Collection<IM> getInvitationMessages(ContactId contactId)
 			throws DbException {
 
-		// query for all invitations
-		BdfDictionary query = BdfDictionary.of(
-				new BdfEntry(TYPE, SHARE_MSG_TYPE_INVITATION)
-		);
-
 		Transaction txn = db.startTransaction(true);
 		try {
 			Contact contact = db.getContact(txn, contactId);
@@ -337,30 +336,51 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IM
 
 			Collection<IM> list = new ArrayList<IM>();
 			Map<MessageId, BdfDictionary> map = clientHelper
-					.getMessageMetadataAsDictionary(txn, group.getId(), query);
+					.getMessageMetadataAsDictionary(txn, group.getId());
 			for (Map.Entry<MessageId, BdfDictionary> m : map.entrySet()) {
 				BdfDictionary d = m.getValue();
+				long type = d.getLong(TYPE);
+				if (type == SHARE_MSG_TYPE_LEAVE ||
+						type == SHARE_MSG_TYPE_ABORT) continue;
 				try {
-					I msg = getIFactory().build(group.getId(), d);
 					MessageStatus status =
 							db.getMessageStatus(txn, contactId, m.getKey());
 					long time = d.getLong(TIME);
 					boolean local = d.getBoolean(LOCAL);
 					boolean read = d.getBoolean(READ, false);
 					boolean available = false;
-					if (!local) {
-						// figure out whether the shareable is still available
-						SharingSessionState s =
-								getSessionState(txn, msg.getSessionId(), true);
-						if (!(s instanceof InviteeSessionState))
-							continue;
-						available = ((InviteeSessionState) s).getState() ==
-								AWAIT_LOCAL_RESPONSE;
+
+					if (type == SHARE_MSG_TYPE_INVITATION) {
+						I msg = getIFactory().build(group.getId(), d);
+						if (!local) {
+							// figure out whether the shareable is still available
+							SharingSessionState s =
+									getSessionState(txn, msg.getSessionId(),
+											true);
+							if (!(s instanceof InviteeSessionState))
+								continue;
+							available = ((InviteeSessionState) s).getState() ==
+									AWAIT_LOCAL_RESPONSE;
+						}
+						IM im = createInvitationRequest(m.getKey(), msg,
+								contactId, available, time, local,
+								status.isSent(), status.isSeen(), read);
+						list.add(im);
+					}
+					else if (type == SHARE_MSG_TYPE_ACCEPT ||
+							type == SHARE_MSG_TYPE_DECLINE) {
+						boolean accept = type == SHARE_MSG_TYPE_ACCEPT;
+						BaseMessage msg = BaseMessage
+								.from(getIFactory(), group.getId(), d);
+						SessionId sessionId = msg.getSessionId();
+						IM im = createInvitationResponse(m.getKey(), sessionId,
+								contactId, accept, time, local,
+								status.isSent(), status.isSeen(), read);
+						list.add(im);
+					}
+					else {
+						throw new RuntimeException("Unexpected Message Type");
 					}
-					IM im = createInvitationMessage(m.getKey(), msg, contactId,
-							available, time, local, status.isSent(),
-							status.isSeen(), read);
-					list.add(im);
 				} catch (FormatException e) {
 					if (LOG.isLoggable(WARNING))
 						LOG.log(WARNING, e.toString(), e);
-- 
GitLab