From 2f7d188a070db5d1247c4ff27841ac932ed6179b Mon Sep 17 00:00:00 2001
From: Torsten Grote <t@grobox.de>
Date: Mon, 1 Aug 2016 20:13:12 -0300
Subject: [PATCH] UI for Sharing Blogs

This commit refactors the code for sharing forums,
so it can be used for sharing blogs as well.

It does not yet include code for responding to blog invitations.
---
 briar-android/AndroidManifest.xml             |  4 +-
 .../res/layout/activity_share_forum.xml       |  2 +-
 ...message.xml => fragment_share_message.xml} |  0
 briar-android/res/menu/blogs_blog_actions.xml | 17 ++++
 briar-android/res/values/strings.xml          |  5 ++
 .../android/ActivityComponent.java            | 14 +--
 .../android/AndroidComponent.java             |  3 +
 .../android/blogs/BlogActivity.java           |  2 +
 .../android/blogs/BlogFragment.java           | 48 +++++++++-
 .../android/forum/ForumActivity.java          |  9 +-
 .../ContactSelectorAdapter.java               |  2 +-
 .../ContactSelectorFragment.java              | 44 +++++++---
 .../SelectableContactListItem.java            |  2 +-
 .../ShareActivity.java}                       | 34 ++++---
 .../ShareMessageFragment.java}                | 88 ++++++++++++-------
 .../SharingStatusActivity.java}               | 10 +--
 .../SharingStatusAdapter.java}                | 10 +--
 .../sharing/BlogSharingManagerImpl.java       | 11 +++
 .../briarproject/sharing/SharingModule.java   |  2 +
 19 files changed, 219 insertions(+), 88 deletions(-)
 rename briar-android/res/layout/{share_forum_message.xml => fragment_share_message.xml} (100%)
 create mode 100644 briar-android/res/menu/blogs_blog_actions.xml
 rename briar-android/src/org/briarproject/android/{forum => sharing}/ContactSelectorAdapter.java (98%)
 rename briar-android/src/org/briarproject/android/{forum => sharing}/ContactSelectorFragment.java (83%)
 rename briar-android/src/org/briarproject/android/{forum => sharing}/SelectableContactListItem.java (95%)
 rename briar-android/src/org/briarproject/android/{forum/ShareForumActivity.java => sharing/ShareActivity.java} (73%)
 rename briar-android/src/org/briarproject/android/{forum/ShareForumMessageFragment.java => sharing/ShareMessageFragment.java} (61%)
 rename briar-android/src/org/briarproject/android/{forum/ForumSharingStatusActivity.java => sharing/SharingStatusActivity.java} (93%)
 rename briar-android/src/org/briarproject/android/{forum/ForumSharingStatusAdapter.java => sharing/SharingStatusAdapter.java} (72%)

diff --git a/briar-android/AndroidManifest.xml b/briar-android/AndroidManifest.xml
index 0249275b5a..55b48260ee 100644
--- a/briar-android/AndroidManifest.xml
+++ b/briar-android/AndroidManifest.xml
@@ -133,7 +133,7 @@
 		</activity>
 
 		<activity
-			android:name=".android.forum.ShareForumActivity"
+			android:name=".android.sharing.ShareActivity"
 			android:label="@string/forums_share_toolbar_header"
 			android:parentActivityName=".android.forum.ForumActivity">
 			<meta-data
@@ -143,7 +143,7 @@
 		</activity>
 
 		<activity
-			android:name=".android.forum.ForumSharingStatusActivity"
+			android:name=".android.sharing.SharingStatusActivity"
 			android:label="@string/forum_sharing_status"
 			android:parentActivityName=".android.forum.ForumActivity">
 			<meta-data
diff --git a/briar-android/res/layout/activity_share_forum.xml b/briar-android/res/layout/activity_share_forum.xml
index b91e96f00b..80f19387f6 100644
--- a/briar-android/res/layout/activity_share_forum.xml
+++ b/briar-android/res/layout/activity_share_forum.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <FrameLayout
-	android:id="@+id/shareForumContainer"
+	android:id="@+id/shareContainer"
 	xmlns:android="http://schemas.android.com/apk/res/android"
 	android:layout_width="match_parent"
 	android:layout_height="match_parent"/>
\ No newline at end of file
diff --git a/briar-android/res/layout/share_forum_message.xml b/briar-android/res/layout/fragment_share_message.xml
similarity index 100%
rename from briar-android/res/layout/share_forum_message.xml
rename to briar-android/res/layout/fragment_share_message.xml
diff --git a/briar-android/res/menu/blogs_blog_actions.xml b/briar-android/res/menu/blogs_blog_actions.xml
new file mode 100644
index 0000000000..ef84cfb201
--- /dev/null
+++ b/briar-android/res/menu/blogs_blog_actions.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu
+	xmlns:android="http://schemas.android.com/apk/res/android"
+	xmlns:app="http://schemas.android.com/apk/res-auto">
+
+	<item
+		android:id="@+id/action_blog_share"
+		android:icon="@drawable/social_share_white"
+		android:title="@string/blogs_sharing_share"
+		app:showAsAction="ifRoom"/>
+
+	<item
+		android:id="@+id/action_blog_sharing_status"
+		android:title="@string/forum_sharing_status"
+		app:showAsAction="never"/>
+
+</menu>
\ No newline at end of file
diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml
index 0c9ce8a08f..164dea6ac2 100644
--- a/briar-android/res/values/strings.xml
+++ b/briar-android/res/values/strings.xml
@@ -113,6 +113,7 @@
 	<string name="forum_share_button">Share Forum</string>
 	<string name="forum_shared_snackbar">Forum shared with chosen contacts</string>
 	<string name="forum_share_message">You may compose an optional invitation message that will be sent to the selected contacts.</string>
+	<string name="forum_share_error">There was an error sharing this forum.</string>
 	<string name="forum_invitation_received">%1$s has shared the forum \"%2$s\" with you.</string>
 	<string name="forum_invitation_sent">You have shared the forum \"%1$s\" with %2$s.</string>
 	<string name="forum_show_invitations">Show Forum Invitations</string>
@@ -304,6 +305,10 @@
 	<string name="blogs_delete_blog_cancel">Keep</string>
 	<string name="blogs_blog_deleted">Blog Deleted</string>
 	<string name="blogs_remove_blog">Remove Blog</string>
+	<string name="blogs_sharing_share">Share Blog</string>
+	<string name="blogs_sharing_error">There was an error sharing this blog.</string>
+	<string name="blogs_sharing_button">Share Blog</string>
+	<string name="blogs_sharing_snackbar">Blog shared with chosen contacts</string>
 
 	<string name="blogs_blog_list">Blog List</string>
 	<string name="blogs_available_blogs">Available Blogs</string>
diff --git a/briar-android/src/org/briarproject/android/ActivityComponent.java b/briar-android/src/org/briarproject/android/ActivityComponent.java
index 7d902e6b4a..8d4d85225e 100644
--- a/briar-android/src/org/briarproject/android/ActivityComponent.java
+++ b/briar-android/src/org/briarproject/android/ActivityComponent.java
@@ -16,13 +16,13 @@ import org.briarproject.android.blogs.WriteBlogPostActivity;
 import org.briarproject.android.contact.ContactListFragment;
 import org.briarproject.android.contact.ConversationActivity;
 import org.briarproject.android.forum.ForumInvitationsActivity;
-import org.briarproject.android.forum.ContactSelectorFragment;
+import org.briarproject.android.sharing.ContactSelectorFragment;
 import org.briarproject.android.forum.CreateForumActivity;
 import org.briarproject.android.forum.ForumActivity;
 import org.briarproject.android.forum.ForumListFragment;
-import org.briarproject.android.forum.ForumSharingStatusActivity;
-import org.briarproject.android.forum.ShareForumActivity;
-import org.briarproject.android.forum.ShareForumMessageFragment;
+import org.briarproject.android.sharing.SharingStatusActivity;
+import org.briarproject.android.sharing.ShareActivity;
+import org.briarproject.android.sharing.ShareMessageFragment;
 import org.briarproject.android.identity.CreateIdentityActivity;
 import org.briarproject.android.introduction.ContactChooserFragment;
 import org.briarproject.android.introduction.IntroductionActivity;
@@ -67,9 +67,9 @@ public interface ActivityComponent {
 
 	void inject(CreateForumActivity activity);
 
-	void inject(ShareForumActivity activity);
+	void inject(ShareActivity activity);
 
-	void inject(ForumSharingStatusActivity activity);
+	void inject(SharingStatusActivity activity);
 
 	void inject(ForumActivity activity);
 
@@ -104,7 +104,7 @@ public interface ActivityComponent {
 	void inject(ShowQrCodeFragment fragment);
 	void inject(ContactChooserFragment fragment);
 	void inject(ContactSelectorFragment fragment);
-	void inject(ShareForumMessageFragment fragment);
+	void inject(ShareMessageFragment fragment);
 	void inject(IntroductionMessageFragment fragment);
 
 }
diff --git a/briar-android/src/org/briarproject/android/AndroidComponent.java b/briar-android/src/org/briarproject/android/AndroidComponent.java
index dbe923c953..a5880d3368 100644
--- a/briar-android/src/org/briarproject/android/AndroidComponent.java
+++ b/briar-android/src/org/briarproject/android/AndroidComponent.java
@@ -8,6 +8,7 @@ import org.briarproject.android.api.ReferenceManager;
 import org.briarproject.android.report.BriarReportSender;
 import org.briarproject.api.blogs.BlogManager;
 import org.briarproject.api.blogs.BlogPostFactory;
+import org.briarproject.api.blogs.BlogSharingManager;
 import org.briarproject.api.contact.ContactExchangeTask;
 import org.briarproject.api.contact.ContactManager;
 import org.briarproject.api.crypto.CryptoComponent;
@@ -93,6 +94,8 @@ public interface AndroidComponent extends CoreEagerSingletons {
 
 	ForumSharingManager forumSharingManager();
 
+	BlogSharingManager blogSharingManager();
+
 	ForumPostFactory forumPostFactory();
 
 	BlogManager blogManager();
diff --git a/briar-android/src/org/briarproject/android/blogs/BlogActivity.java b/briar-android/src/org/briarproject/android/blogs/BlogActivity.java
index ceb80f61ad..866b191d96 100644
--- a/briar-android/src/org/briarproject/android/blogs/BlogActivity.java
+++ b/briar-android/src/org/briarproject/android/blogs/BlogActivity.java
@@ -32,6 +32,7 @@ public class BlogActivity extends BriarActivity implements BlogPostListener,
 		OnBlogPostClickListener, BaseFragmentListener {
 
 	static final int REQUEST_WRITE_POST = 1;
+	static final int REQUEST_SHARE = 2;
 	static final String BLOG_NAME = "briar.BLOG_NAME";
 	static final String IS_MY_BLOG = "briar.IS_MY_BLOG";
 	static final String IS_NEW_BLOG = "briar.IS_NEW_BLOG";
@@ -185,6 +186,7 @@ public class BlogActivity extends BriarActivity implements BlogPostListener,
 	@Override
 	protected void onActivityResult(int requestCode, int resultCode,
 			Intent data) {
+		super.onActivityResult(requestCode, resultCode, data);
 
 		// The BlogPostAddedEvent arrives when the controller is not listening,
 		// so we need to manually reload the blog posts :(
diff --git a/briar-android/src/org/briarproject/android/blogs/BlogFragment.java b/briar-android/src/org/briarproject/android/blogs/BlogFragment.java
index ec3762b581..a6e46b3fef 100644
--- a/briar-android/src/org/briarproject/android/blogs/BlogFragment.java
+++ b/briar-android/src/org/briarproject/android/blogs/BlogFragment.java
@@ -23,6 +23,8 @@ import org.briarproject.android.blogs.BlogController.BlogPostListener;
 import org.briarproject.android.blogs.BlogPostAdapter.OnBlogPostClickListener;
 import org.briarproject.android.controller.handler.UiResultHandler;
 import org.briarproject.android.fragment.BaseFragment;
+import org.briarproject.android.sharing.ShareActivity;
+import org.briarproject.android.sharing.SharingStatusActivity;
 import org.briarproject.android.util.BriarRecyclerView;
 import org.briarproject.api.sync.GroupId;
 
@@ -30,6 +32,9 @@ import java.util.Collection;
 
 import javax.inject.Inject;
 
+import static android.app.Activity.RESULT_OK;
+import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
+import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
 import static android.support.design.widget.Snackbar.LENGTH_LONG;
 import static android.support.v4.app.ActivityOptionsCompat.makeCustomAnimation;
 import static android.widget.Toast.LENGTH_SHORT;
@@ -37,7 +42,10 @@ import static org.briarproject.android.BriarActivity.GROUP_ID;
 import static org.briarproject.android.blogs.BlogActivity.BLOG_NAME;
 import static org.briarproject.android.blogs.BlogActivity.IS_MY_BLOG;
 import static org.briarproject.android.blogs.BlogActivity.IS_NEW_BLOG;
+import static org.briarproject.android.blogs.BlogActivity.REQUEST_SHARE;
 import static org.briarproject.android.blogs.BlogActivity.REQUEST_WRITE_POST;
+import static org.briarproject.android.sharing.ShareActivity.BLOG;
+import static org.briarproject.android.sharing.ShareActivity.SHAREABLE;
 
 public class BlogFragment extends BaseFragment implements BlogPostListener {
 
@@ -136,12 +144,18 @@ public class BlogFragment extends BaseFragment implements BlogPostListener {
 	public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
 		if (myBlog) {
 			inflater.inflate(R.menu.blogs_my_blog_actions, menu);
+		} else {
+			inflater.inflate(R.menu.blogs_blog_actions, menu);
 		}
 		super.onCreateOptionsMenu(menu, inflater);
 	}
 
 	@Override
 	public boolean onOptionsItemSelected(final MenuItem item) {
+		ActivityOptionsCompat options =
+				makeCustomAnimation(getActivity(),
+						android.R.anim.slide_in_left,
+						android.R.anim.slide_out_right);
 		switch (item.getItemId()) {
 			case android.R.id.home:
 				getActivity().onBackPressed();
@@ -151,18 +165,37 @@ public class BlogFragment extends BaseFragment implements BlogPostListener {
 						new Intent(getActivity(), WriteBlogPostActivity.class);
 				i.putExtra(GROUP_ID, groupId.getBytes());
 				i.putExtra(BLOG_NAME, blogName);
-				ActivityOptionsCompat options =
-						makeCustomAnimation(getActivity(),
-								android.R.anim.slide_in_left,
-								android.R.anim.slide_out_right);
 				ActivityCompat.startActivityForResult(getActivity(), i,
 						REQUEST_WRITE_POST, options.toBundle());
 				return true;
+			case R.id.action_blog_share:
+				Intent i2 = new Intent(getActivity(), ShareActivity.class);
+				i2.setFlags(FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_SINGLE_TOP);
+				i2.putExtra(GROUP_ID, groupId.getBytes());
+				i2.putExtra(SHAREABLE, BLOG);
+				startActivityForResult(i2, REQUEST_SHARE, options.toBundle());
+				return true;
+			case R.id.action_blog_sharing_status:
+				Intent i3 =
+						new Intent(getActivity(), SharingStatusActivity.class);
+				i3.setFlags(FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_SINGLE_TOP);
+				i3.putExtra(GROUP_ID, groupId.getBytes());
+				startActivity(i3, options.toBundle());
+				return true;
 			default:
 				return super.onOptionsItemSelected(item);
 		}
 	}
 
+	@Override
+	public void onActivityResult(int request, int result, Intent data) {
+		super.onActivityResult(request, result, data);
+
+		if (request == REQUEST_SHARE && result == RESULT_OK) {
+			displaySnackbar(R.string.blogs_sharing_snackbar);
+		}
+	}
+
 	@Override
 	public String getUniqueTag() {
 		return TAG;
@@ -202,6 +235,13 @@ public class BlogFragment extends BaseFragment implements BlogPostListener {
 		loadData(true);
 	}
 
+	private void displaySnackbar(int stringId) {
+		Snackbar snackbar =
+				Snackbar.make(list, stringId, Snackbar.LENGTH_SHORT);
+		snackbar.getView().setBackgroundResource(R.color.briar_primary);
+		snackbar.show();
+	}
+
 	private void showDeleteDialog() {
 		DialogInterface.OnClickListener okListener =
 				new DialogInterface.OnClickListener() {
diff --git a/briar-android/src/org/briarproject/android/forum/ForumActivity.java b/briar-android/src/org/briarproject/android/forum/ForumActivity.java
index 02a78caccb..383992a8e8 100644
--- a/briar-android/src/org/briarproject/android/forum/ForumActivity.java
+++ b/briar-android/src/org/briarproject/android/forum/ForumActivity.java
@@ -33,6 +33,8 @@ import org.briarproject.android.ActivityComponent;
 import org.briarproject.android.BriarActivity;
 import org.briarproject.android.api.AndroidNotificationManager;
 import org.briarproject.android.controller.handler.UiResultHandler;
+import org.briarproject.android.sharing.ShareActivity;
+import org.briarproject.android.sharing.SharingStatusActivity;
 import org.briarproject.android.util.AndroidUtils;
 import org.briarproject.android.util.BriarRecyclerView;
 import org.briarproject.android.util.TrustIndicatorView;
@@ -57,6 +59,8 @@ import static android.view.View.GONE;
 import static android.view.View.INVISIBLE;
 import static android.view.View.VISIBLE;
 import static android.widget.Toast.LENGTH_SHORT;
+import static org.briarproject.android.sharing.ShareActivity.FORUM;
+import static org.briarproject.android.sharing.ShareActivity.SHAREABLE;
 
 public class ForumActivity extends BriarActivity implements
 		ForumController.ForumPostListener {
@@ -220,15 +224,16 @@ public class ForumActivity extends BriarActivity implements
 				showTextInput(null);
 				return true;
 			case R.id.action_forum_share:
-				Intent i2 = new Intent(this, ShareForumActivity.class);
+				Intent i2 = new Intent(this, ShareActivity.class);
 				i2.setFlags(FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_SINGLE_TOP);
 				i2.putExtra(GROUP_ID, groupId.getBytes());
+				i2.putExtra(SHAREABLE, FORUM);
 				ActivityCompat
 						.startActivityForResult(this, i2, REQUEST_FORUM_SHARED,
 								options.toBundle());
 				return true;
 			case R.id.action_forum_sharing_status:
-				Intent i3 = new Intent(this, ForumSharingStatusActivity.class);
+				Intent i3 = new Intent(this, SharingStatusActivity.class);
 				i3.setFlags(FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_SINGLE_TOP);
 				i3.putExtra(GROUP_ID, groupId.getBytes());
 				ActivityCompat.startActivity(this, i3, options.toBundle());
diff --git a/briar-android/src/org/briarproject/android/forum/ContactSelectorAdapter.java b/briar-android/src/org/briarproject/android/sharing/ContactSelectorAdapter.java
similarity index 98%
rename from briar-android/src/org/briarproject/android/forum/ContactSelectorAdapter.java
rename to briar-android/src/org/briarproject/android/sharing/ContactSelectorAdapter.java
index 9a2fe45906..d940c48dc6 100644
--- a/briar-android/src/org/briarproject/android/forum/ContactSelectorAdapter.java
+++ b/briar-android/src/org/briarproject/android/sharing/ContactSelectorAdapter.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.forum;
+package org.briarproject.android.sharing;
 
 import android.content.Context;
 import android.graphics.Color;
diff --git a/briar-android/src/org/briarproject/android/forum/ContactSelectorFragment.java b/briar-android/src/org/briarproject/android/sharing/ContactSelectorFragment.java
similarity index 83%
rename from briar-android/src/org/briarproject/android/forum/ContactSelectorFragment.java
rename to briar-android/src/org/briarproject/android/sharing/ContactSelectorFragment.java
index 99f1f41c61..6ace473db2 100644
--- a/briar-android/src/org/briarproject/android/forum/ContactSelectorFragment.java
+++ b/briar-android/src/org/briarproject/android/sharing/ContactSelectorFragment.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.forum;
+package org.briarproject.android.sharing;
 
 import android.content.Context;
 import android.os.Build;
@@ -18,6 +18,7 @@ import org.briarproject.android.contact.BaseContactListAdapter;
 import org.briarproject.android.contact.ContactListItem;
 import org.briarproject.android.fragment.BaseFragment;
 import org.briarproject.android.util.BriarRecyclerView;
+import org.briarproject.api.blogs.BlogSharingManager;
 import org.briarproject.api.contact.Contact;
 import org.briarproject.api.contact.ContactId;
 import org.briarproject.api.contact.ContactManager;
@@ -37,8 +38,11 @@ import javax.inject.Inject;
 
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.android.forum.ShareForumActivity.CONTACTS;
-import static org.briarproject.android.forum.ShareForumActivity.getContactsFromIds;
+import static org.briarproject.android.sharing.ShareActivity.BLOG;
+import static org.briarproject.android.sharing.ShareActivity.CONTACTS;
+import static org.briarproject.android.sharing.ShareActivity.FORUM;
+import static org.briarproject.android.sharing.ShareActivity.SHAREABLE;
+import static org.briarproject.android.sharing.ShareActivity.getContactsFromIds;
 import static org.briarproject.api.sharing.SharingConstants.GROUP_ID;
 
 public class ContactSelectorFragment extends BaseFragment implements
@@ -49,7 +53,7 @@ public class ContactSelectorFragment extends BaseFragment implements
 	private static final Logger LOG =
 			Logger.getLogger(ContactSelectorFragment.class.getName());
 
-	private ShareForumActivity shareForumActivity;
+	private ShareActivity shareActivity;
 	private Menu menu;
 	private BriarRecyclerView list;
 	private ContactSelectorAdapter adapter;
@@ -62,13 +66,18 @@ public class ContactSelectorFragment extends BaseFragment implements
 	protected volatile IdentityManager identityManager;
 	@Inject
 	protected volatile ForumSharingManager forumSharingManager;
+	@Inject
+	volatile BlogSharingManager blogSharingManager;
 
-	protected volatile GroupId groupId;
+	private volatile GroupId groupId;
+	private volatile int shareable;
 
-	public static ContactSelectorFragment newInstance(GroupId groupId) {
+	public static ContactSelectorFragment newInstance(int shareable,
+			GroupId groupId) {
 
 		Bundle args = new Bundle();
 		args.putByteArray(GROUP_ID, groupId.getBytes());
+		args.putInt(SHAREABLE, shareable);
 		ContactSelectorFragment fragment = new ContactSelectorFragment();
 		fragment.setArguments(args);
 		return fragment;
@@ -83,7 +92,7 @@ public class ContactSelectorFragment extends BaseFragment implements
 	public void onAttach(Context context) {
 		super.onAttach(context);
 		try {
-			shareForumActivity = (ShareForumActivity) context;
+			shareActivity = (ShareActivity) context;
 		} catch (ClassCastException e) {
 			throw new InstantiationError(
 					"This fragment is only meant to be attached to the ShareForumActivity");
@@ -97,6 +106,7 @@ public class ContactSelectorFragment extends BaseFragment implements
 		setHasOptionsMenu(true);
 		groupId = new GroupId(getArguments().getByteArray(GROUP_ID));
 		if (groupId == null) throw new IllegalStateException("No GroupId");
+		shareable = getArguments().getInt(SHAREABLE);
 	}
 
 	@Override
@@ -121,7 +131,7 @@ public class ContactSelectorFragment extends BaseFragment implements
 		if (savedInstanceState != null) {
 			ArrayList<Integer> intContacts =
 					savedInstanceState.getIntegerArrayList(CONTACTS);
-			selectedContacts = ShareForumActivity.getContactsFromIntegers(
+			selectedContacts = ShareActivity.getContactsFromIntegers(
 					intContacts);
 		}
 
@@ -160,11 +170,11 @@ public class ContactSelectorFragment extends BaseFragment implements
 		// Handle presses on the action bar items
 		switch (item.getItemId()) {
 			case android.R.id.home:
-				shareForumActivity.onBackPressed();
+				shareActivity.onBackPressed();
 				return true;
 			case R.id.action_share_forum:
 				selectedContacts = adapter.getSelectedContactIds();
-				shareForumActivity.showMessageScreen(groupId, selectedContacts);
+				shareActivity.showMessageScreen(groupId, selectedContacts);
 				return true;
 			default:
 				return super.onOptionsItemSelected(item);
@@ -185,7 +195,7 @@ public class ContactSelectorFragment extends BaseFragment implements
 	}
 
 	private void loadContacts(final Collection<ContactId> selection) {
-		shareForumActivity.runOnDbThread(new Runnable() {
+		listener.runOnDbThread(new Runnable() {
 			@Override
 			public void run() {
 				try {
@@ -199,8 +209,14 @@ public class ContactSelectorFragment extends BaseFragment implements
 						boolean selected = selection != null &&
 								selection.contains(c.getId());
 						// do we have already some sharing with that contact?
-						boolean disabled =
-								!forumSharingManager.canBeShared(groupId, c);
+						boolean disabled = true;
+						if (shareable == FORUM) {
+							disabled = !forumSharingManager
+									.canBeShared(groupId, c);
+						} else if (shareable == BLOG) {
+							disabled = !blogSharingManager
+									.canBeShared(groupId, c);
+						}
 						contacts.add(new SelectableContactListItem(c,
 								localAuthor, groupId, selected, disabled));
 					}
@@ -218,7 +234,7 @@ public class ContactSelectorFragment extends BaseFragment implements
 	}
 
 	private void displayContacts(final List<ContactListItem> contacts) {
-		shareForumActivity.runOnUiThread(new Runnable() {
+		shareActivity.runOnUiThread(new Runnable() {
 			@Override
 			public void run() {
 				if (!contacts.isEmpty()) adapter.addAll(contacts);
diff --git a/briar-android/src/org/briarproject/android/forum/SelectableContactListItem.java b/briar-android/src/org/briarproject/android/sharing/SelectableContactListItem.java
similarity index 95%
rename from briar-android/src/org/briarproject/android/forum/SelectableContactListItem.java
rename to briar-android/src/org/briarproject/android/sharing/SelectableContactListItem.java
index fa5ad2284f..0d713fda2f 100644
--- a/briar-android/src/org/briarproject/android/forum/SelectableContactListItem.java
+++ b/briar-android/src/org/briarproject/android/sharing/SelectableContactListItem.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.forum;
+package org.briarproject.android.sharing;
 
 import org.briarproject.android.contact.ContactListItem;
 import org.briarproject.android.contact.ConversationItem;
diff --git a/briar-android/src/org/briarproject/android/forum/ShareForumActivity.java b/briar-android/src/org/briarproject/android/sharing/ShareActivity.java
similarity index 73%
rename from briar-android/src/org/briarproject/android/forum/ShareForumActivity.java
rename to briar-android/src/org/briarproject/android/sharing/ShareActivity.java
index d789e854f6..be0a6e8db6 100644
--- a/briar-android/src/org/briarproject/android/forum/ShareForumActivity.java
+++ b/briar-android/src/org/briarproject/android/sharing/ShareActivity.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.forum;
+package org.briarproject.android.sharing;
 
 import android.content.Intent;
 import android.os.Bundle;
@@ -15,11 +15,16 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 
-// TODO extend the BriarFragmentActivity ?
-public class ShareForumActivity extends BriarActivity implements
+public class ShareActivity extends BriarActivity implements
 		BaseFragment.BaseFragmentListener {
 
-	public final static String CONTACTS = "contacts";
+	public final static String SHAREABLE = "shareable";
+	public final static int FORUM = 1;
+	public final static int BLOG = 2;
+
+	final static String CONTACTS = "contacts";
+
+	private int shareable;
 
 	@Override
 	public void onCreate(Bundle savedInstanceState) {
@@ -32,11 +37,14 @@ public class ShareForumActivity extends BriarActivity implements
 		if (b == null) throw new IllegalStateException("No GroupId");
 		GroupId groupId = new GroupId(b);
 
+		shareable = i.getIntExtra(SHAREABLE, 0);
+		if (shareable == 0) throw new IllegalStateException("No Shareable");
+
 		if (savedInstanceState == null) {
 			ContactSelectorFragment contactSelectorFragment =
-					ContactSelectorFragment.newInstance(groupId);
+					ContactSelectorFragment.newInstance(shareable, groupId);
 			getSupportFragmentManager().beginTransaction()
-					.add(R.id.shareForumContainer, contactSelectorFragment)
+					.add(R.id.shareContainer, contactSelectorFragment)
 					.commit();
 		}
 	}
@@ -46,24 +54,24 @@ public class ShareForumActivity extends BriarActivity implements
 		component.inject(this);
 	}
 
-	public void showMessageScreen(GroupId groupId,
+	void showMessageScreen(GroupId groupId,
 			Collection<ContactId> contacts) {
 
-		ShareForumMessageFragment messageFragment =
-				ShareForumMessageFragment.newInstance(groupId, contacts);
+		ShareMessageFragment messageFragment =
+				ShareMessageFragment.newInstance(shareable, groupId, contacts);
 
 		getSupportFragmentManager().beginTransaction()
 				.setCustomAnimations(android.R.anim.fade_in,
 						android.R.anim.fade_out,
 						android.R.anim.slide_in_left,
 						android.R.anim.slide_out_right)
-				.replace(R.id.shareForumContainer, messageFragment,
+				.replace(R.id.shareContainer, messageFragment,
 						ContactSelectorFragment.TAG)
 				.addToBackStack(null)
 				.commit();
 	}
 
-	public static ArrayList<Integer> getContactsFromIds(
+	static ArrayList<Integer> getContactsFromIds(
 			Collection<ContactId> contacts) {
 
 		// transform ContactIds to Integers so they can be added to a bundle
@@ -74,13 +82,13 @@ public class ShareForumActivity extends BriarActivity implements
 		return intContacts;
 	}
 
-	public void sharingSuccessful(View v) {
+	void sharingSuccessful(View v) {
 		setResult(RESULT_OK);
 		hideSoftKeyboard(v);
 		supportFinishAfterTransition();
 	}
 
-	protected static Collection<ContactId> getContactsFromIntegers(
+	static Collection<ContactId> getContactsFromIntegers(
 			ArrayList<Integer> intContacts) {
 
 		// turn contact integers from a bundle back to ContactIds
diff --git a/briar-android/src/org/briarproject/android/forum/ShareForumMessageFragment.java b/briar-android/src/org/briarproject/android/sharing/ShareMessageFragment.java
similarity index 61%
rename from briar-android/src/org/briarproject/android/forum/ShareForumMessageFragment.java
rename to briar-android/src/org/briarproject/android/sharing/ShareMessageFragment.java
index e8682a1369..9e9fcac391 100644
--- a/briar-android/src/org/briarproject/android/forum/ShareForumMessageFragment.java
+++ b/briar-android/src/org/briarproject/android/sharing/ShareMessageFragment.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.forum;
+package org.briarproject.android.sharing;
 
 import android.content.Context;
 import android.os.Bundle;
@@ -14,6 +14,8 @@ import android.widget.Toast;
 import org.briarproject.R;
 import org.briarproject.android.ActivityComponent;
 import org.briarproject.android.fragment.BaseFragment;
+import org.briarproject.api.blogs.BlogManager;
+import org.briarproject.api.blogs.BlogSharingManager;
 import org.briarproject.api.contact.ContactId;
 import org.briarproject.api.db.DbException;
 import org.briarproject.api.forum.ForumSharingManager;
@@ -27,31 +29,40 @@ import javax.inject.Inject;
 
 import static android.widget.Toast.LENGTH_SHORT;
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.android.forum.ShareForumActivity.CONTACTS;
-import static org.briarproject.android.forum.ShareForumActivity.getContactsFromIds;
+import static org.briarproject.android.sharing.ShareActivity.BLOG;
+import static org.briarproject.android.sharing.ShareActivity.CONTACTS;
+import static org.briarproject.android.sharing.ShareActivity.FORUM;
+import static org.briarproject.android.sharing.ShareActivity.SHAREABLE;
+import static org.briarproject.android.sharing.ShareActivity.getContactsFromIds;
 import static org.briarproject.api.sharing.SharingConstants.GROUP_ID;
 
-public class ShareForumMessageFragment extends BaseFragment {
+public class ShareMessageFragment extends BaseFragment {
 
 	public final static String TAG = "IntroductionMessageFragment";
 
 	private static final Logger LOG =
-			Logger.getLogger(ShareForumMessageFragment.class.getName());
+			Logger.getLogger(ShareMessageFragment.class.getName());
 
-	private ShareForumActivity shareForumActivity;
+	private ShareActivity shareActivity;
 	private ViewHolder ui;
 
 	// Fields that are accessed from background threads must be volatile
 	@Inject
 	protected volatile ForumSharingManager forumSharingManager;
+	@Inject
+	protected volatile BlogSharingManager blogSharingManager;
 	private volatile GroupId groupId;
+	private volatile int shareable;
 	private volatile Collection<ContactId> contacts;
 
-	public static ShareForumMessageFragment newInstance(GroupId groupId, Collection<ContactId> contacts) {
+	public static ShareMessageFragment newInstance(int shareable,
+			GroupId groupId, Collection<ContactId> contacts) {
+
 		Bundle args = new Bundle();
 		args.putByteArray(GROUP_ID, groupId.getBytes());
+		args.putInt(SHAREABLE, shareable);
 		args.putIntegerArrayList(CONTACTS, getContactsFromIds(contacts));
-		ShareForumMessageFragment fragment = new ShareForumMessageFragment();
+		ShareMessageFragment fragment = new ShareMessageFragment();
 		fragment.setArguments(args);
 		return fragment;
 	}
@@ -60,7 +71,7 @@ public class ShareForumMessageFragment extends BaseFragment {
 	public void onAttach(Context context) {
 		super.onAttach(context);
 		try {
-			shareForumActivity = (ShareForumActivity) context;
+			shareActivity = (ShareActivity) context;
 		} catch (ClassCastException e) {
 			throw new InstantiationError(
 					"This fragment is only meant to be attached to the ShareForumActivity");
@@ -71,17 +82,31 @@ public class ShareForumMessageFragment extends BaseFragment {
 	public View onCreateView(LayoutInflater inflater, ViewGroup container,
 			Bundle savedInstanceState) {
 
+		// allow for home button to act as back button
+		setHasOptionsMenu(true);
+
+		// get groupID, shareable type and contactIDs from fragment arguments
+		groupId = new GroupId(getArguments().getByteArray(GROUP_ID));
+		shareable = getArguments().getInt(SHAREABLE);
+		ArrayList<Integer> intContacts =
+				getArguments().getIntegerArrayList(CONTACTS);
+		if (intContacts == null) throw new IllegalArgumentException();
+		contacts = ShareActivity.getContactsFromIntegers(intContacts);
+
 		// change toolbar text
-		ActionBar actionBar = shareForumActivity.getSupportActionBar();
+		ActionBar actionBar = shareActivity.getSupportActionBar();
 		if (actionBar != null) {
-			actionBar.setTitle(R.string.forum_share_button);
+			if (shareable == FORUM) {
+				actionBar.setTitle(R.string.forum_share_button);
+			} else if (shareable == BLOG) {
+				actionBar.setTitle(R.string.blogs_sharing_button);
+			} else {
+				throw new IllegalArgumentException("Invalid Shareable Type!");
+			}
 		}
 
-		// allow for home button to act as back button
-		setHasOptionsMenu(true);
-
 		// inflate view
-		View v = inflater.inflate(R.layout.share_forum_message, container,
+		View v = inflater.inflate(R.layout.fragment_share_message, container,
 				false);
 		ui = new ViewHolder(v);
 		ui.button.setOnClickListener(new View.OnClickListener() {
@@ -90,13 +115,9 @@ public class ShareForumMessageFragment extends BaseFragment {
 				onButtonClick();
 			}
 		});
-
-		// get groupID and contactIDs from fragment arguments
-		groupId = new GroupId(getArguments().getByteArray(GROUP_ID));
-		ArrayList<Integer> intContacts =
-				getArguments().getIntegerArrayList(CONTACTS);
-		if (intContacts == null) throw new IllegalArgumentException();
-		contacts = ShareForumActivity.getContactsFromIntegers(intContacts);
+		if (shareable == BLOG) {
+			ui.button.setText(getString(R.string.blogs_sharing_button));
+		}
 
 		return v;
 	}
@@ -105,7 +126,7 @@ public class ShareForumMessageFragment extends BaseFragment {
 	public boolean onOptionsItemSelected(final MenuItem item) {
 		switch (item.getItemId()) {
 			case android.R.id.home:
-				shareForumActivity.onBackPressed();
+				shareActivity.onBackPressed();
 				return true;
 			default:
 				return super.onOptionsItemSelected(item);
@@ -122,7 +143,7 @@ public class ShareForumMessageFragment extends BaseFragment {
 		component.inject(this);
 	}
 
-	public void onButtonClick() {
+	private void onButtonClick() {
 		// disable button to prevent accidental double invitations
 		ui.button.setEnabled(false);
 
@@ -130,17 +151,21 @@ public class ShareForumMessageFragment extends BaseFragment {
 		shareForum(msg);
 
 		// don't wait for the introduction to be made before finishing activity
-		shareForumActivity.sharingSuccessful(ui.message);
+		shareActivity.sharingSuccessful(ui.message);
 	}
 
 	private void shareForum(final String msg) {
-		shareForumActivity.runOnDbThread(new Runnable() {
+		listener.runOnDbThread(new Runnable() {
 			@Override
 			public void run() {
 				try {
 					for (ContactId c : contacts) {
-						forumSharingManager.sendInvitation(groupId, c,
-								msg);
+						if (shareable == FORUM) {
+							forumSharingManager.sendInvitation(groupId, c,
+									msg);
+						} else if (shareable == BLOG) {
+							blogSharingManager.sendInvitation(groupId, c, msg);
+						}
 					}
 				} catch (DbException e) {
 					sharingError();
@@ -152,11 +177,12 @@ public class ShareForumMessageFragment extends BaseFragment {
 	}
 
 	private void sharingError() {
-		shareForumActivity.runOnUiThread(new Runnable() {
+		shareActivity.runOnUiThread(new Runnable() {
 			@Override
 			public void run() {
-				Toast.makeText(shareForumActivity,
-						R.string.introduction_error, LENGTH_SHORT).show();
+				int res = R.string.forum_share_error;
+				if (shareable == BLOG) res = R.string.blogs_sharing_error;
+				Toast.makeText(shareActivity, res, LENGTH_SHORT).show();
 			}
 		});
 	}
diff --git a/briar-android/src/org/briarproject/android/forum/ForumSharingStatusActivity.java b/briar-android/src/org/briarproject/android/sharing/SharingStatusActivity.java
similarity index 93%
rename from briar-android/src/org/briarproject/android/forum/ForumSharingStatusActivity.java
rename to briar-android/src/org/briarproject/android/sharing/SharingStatusActivity.java
index 5da3d212c0..b9c51cbe61 100644
--- a/briar-android/src/org/briarproject/android/forum/ForumSharingStatusActivity.java
+++ b/briar-android/src/org/briarproject/android/sharing/SharingStatusActivity.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.forum;
+package org.briarproject.android.sharing;
 
 import android.content.Intent;
 import android.os.Bundle;
@@ -26,11 +26,11 @@ import javax.inject.Inject;
 
 import static java.util.logging.Level.WARNING;
 
-public class ForumSharingStatusActivity extends BriarActivity {
+public class SharingStatusActivity extends BriarActivity {
 
 	private GroupId groupId;
 	private BriarRecyclerView sharedByList, sharedWithList;
-	private ForumSharingStatusAdapter sharedByAdapter, sharedWithAdapter;
+	private SharingStatusAdapter sharedByAdapter, sharedWithAdapter;
 
 	// Fields that are accessed from background threads must be volatile
 	@Inject
@@ -53,13 +53,13 @@ public class ForumSharingStatusActivity extends BriarActivity {
 		groupId = new GroupId(b);
 
 		sharedByList = (BriarRecyclerView) findViewById(R.id.sharedByView);
-		sharedByAdapter = new ForumSharingStatusAdapter(this);
+		sharedByAdapter = new SharingStatusAdapter(this);
 		sharedByList.setLayoutManager(new LinearLayoutManager(this));
 		sharedByList.setAdapter(sharedByAdapter);
 		sharedByList.setEmptyText(getString(R.string.nobody));
 
 		sharedWithList = (BriarRecyclerView) findViewById(R.id.sharedWithView);
-		sharedWithAdapter = new ForumSharingStatusAdapter(this);
+		sharedWithAdapter = new SharingStatusAdapter(this);
 		sharedWithList.setLayoutManager(new LinearLayoutManager(this));
 		sharedWithList.setAdapter(sharedWithAdapter);
 		sharedWithList.setEmptyText(getString(R.string.nobody));
diff --git a/briar-android/src/org/briarproject/android/forum/ForumSharingStatusAdapter.java b/briar-android/src/org/briarproject/android/sharing/SharingStatusAdapter.java
similarity index 72%
rename from briar-android/src/org/briarproject/android/forum/ForumSharingStatusAdapter.java
rename to briar-android/src/org/briarproject/android/sharing/SharingStatusAdapter.java
index 3d52480def..18f70fe78b 100644
--- a/briar-android/src/org/briarproject/android/forum/ForumSharingStatusAdapter.java
+++ b/briar-android/src/org/briarproject/android/sharing/SharingStatusAdapter.java
@@ -1,22 +1,18 @@
-package org.briarproject.android.forum;
+package org.briarproject.android.sharing;
 
 import android.content.Context;
-import android.support.v4.content.ContextCompat;
-import android.text.format.DateUtils;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.TextView;
 
 import org.briarproject.R;
 import org.briarproject.android.contact.BaseContactListAdapter;
 import org.briarproject.android.contact.ContactListItem;
 
-public class ForumSharingStatusAdapter
+class SharingStatusAdapter
 		extends BaseContactListAdapter<BaseContactListAdapter.BaseContactHolder> {
 
-	public ForumSharingStatusAdapter(Context context) {
+	SharingStatusAdapter(Context context) {
 		super(context, null);
 	}
 
diff --git a/briar-core/src/org/briarproject/sharing/BlogSharingManagerImpl.java b/briar-core/src/org/briarproject/sharing/BlogSharingManagerImpl.java
index 5632ea9940..5506676414 100644
--- a/briar-core/src/org/briarproject/sharing/BlogSharingManagerImpl.java
+++ b/briar-core/src/org/briarproject/sharing/BlogSharingManagerImpl.java
@@ -12,6 +12,7 @@ import org.briarproject.api.clients.ClientHelper;
 import org.briarproject.api.clients.MessageQueueManager;
 import org.briarproject.api.clients.PrivateGroupFactory;
 import org.briarproject.api.clients.SessionId;
+import org.briarproject.api.contact.Contact;
 import org.briarproject.api.contact.ContactId;
 import org.briarproject.api.data.BdfDictionary;
 import org.briarproject.api.data.BdfList;
@@ -47,6 +48,8 @@ class BlogSharingManagerImpl extends
 			"bee438b5de0b3a685badc4e49d76e72d"
 					+ "21e01c4b569a775112756bdae267a028"));
 
+	private final BlogManager blogManager;
+
 	private final SFactory sFactory;
 	private final IFactory iFactory;
 	private final ISFactory isFactory;
@@ -64,6 +67,7 @@ class BlogSharingManagerImpl extends
 		super(db, messageQueueManager, clientHelper, metadataParser,
 				metadataEncoder, random, privateGroupFactory, clock);
 
+		this.blogManager = blogManager;
 		sFactory = new SFactory(authorFactory, blogFactory, blogManager);
 		iFactory = new IFactory();
 		isFactory = new ISFactory();
@@ -77,6 +81,13 @@ class BlogSharingManagerImpl extends
 		return CLIENT_ID;
 	}
 
+	@Override
+	public boolean canBeShared(GroupId g, Contact c) throws DbException {
+		Blog b = blogManager.getPersonalBlog(c.getAuthor());
+		if (b.getId().equals(g)) return false;
+		return super.canBeShared(g, c);
+	}
+
 	@Override
 	protected BlogInvitationRequest createInvitationRequest(MessageId id,
 			BlogInvitation msg, ContactId contactId, boolean available,
diff --git a/briar-core/src/org/briarproject/sharing/SharingModule.java b/briar-core/src/org/briarproject/sharing/SharingModule.java
index 3af07e1292..a098fa1e14 100644
--- a/briar-core/src/org/briarproject/sharing/SharingModule.java
+++ b/briar-core/src/org/briarproject/sharing/SharingModule.java
@@ -27,6 +27,8 @@ public class SharingModule {
 		ForumSharingValidator forumSharingValidator;
 		@Inject
 		ForumSharingManager forumSharingManager;
+		@Inject
+		BlogSharingManager blogSharingManager;
 	}
 
 	@Provides
-- 
GitLab