diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml
index 42c797924..3d9e47c00 100644
--- a/briar-android/res/values/strings.xml
+++ b/briar-android/res/values/strings.xml
@@ -155,7 +155,7 @@
- %d messages
This group is empty
- This group is dissolved
+ This group has been dissolved
Remove
Create Private Group
This group is empty.\n\nYou can use the pen icon at the top to compose the first message.
@@ -168,11 +168,16 @@
Message received
Member List
Invite Members
+ joined the group.
Leave Group
Confirm Leaving Group
Are you sure that you want to leave this group?
Dissolve Group
- joined the group.
+ Confirm Dissolving Group
+ Are you sure that you want to dissolve this group?\n\nAll other members will not be able to continue their conversation and might not receive the latest messages.
+ Dissolve
+ Group Has Been Dissolved
+ The creator of this group has dissolved it.\n\nYou can no longer write messages to the group and might not receive all posts that have been written.
Group Invitations
@@ -188,9 +193,6 @@
You declined the group invitation from %s.
%s accepted your group invitation.
%s declined your group invitation.
- Confirm Dissolving Group
- Are you sure that you want to dissolve this group?\n\nAll other members will not be able to continue their conversation and might not receive the latest messages.
- Dissolve
You don\'t have any forums yet.\n\nWhy don\'t you create a new one yourself by tapping the + icon at the top?\n\nYou can also ask your contacts to share forums with you.
diff --git a/briar-android/src/org/briarproject/android/forum/ForumControllerImpl.java b/briar-android/src/org/briarproject/android/forum/ForumControllerImpl.java
index a3b7fde89..55c8f817b 100644
--- a/briar-android/src/org/briarproject/android/forum/ForumControllerImpl.java
+++ b/briar-android/src/org/briarproject/android/forum/ForumControllerImpl.java
@@ -4,6 +4,7 @@ import android.support.annotation.Nullable;
import org.briarproject.android.api.AndroidNotificationManager;
import org.briarproject.android.controller.handler.ResultExceptionHandler;
+import org.briarproject.android.threaded.ThreadListController.ThreadListListener;
import org.briarproject.android.threaded.ThreadListControllerImpl;
import org.briarproject.api.clients.MessageTracker.GroupCount;
import org.briarproject.api.crypto.CryptoExecutor;
@@ -32,7 +33,7 @@ import static java.lang.Math.max;
import static java.util.logging.Level.WARNING;
public class ForumControllerImpl
- extends ThreadListControllerImpl
+ extends ThreadListControllerImpl>
implements ForumController {
private static final Logger LOG =
diff --git a/briar-android/src/org/briarproject/android/privategroup/conversation/GroupActivity.java b/briar-android/src/org/briarproject/android/privategroup/conversation/GroupActivity.java
index dcdabb5fe..e59f6cdac 100644
--- a/briar-android/src/org/briarproject/android/privategroup/conversation/GroupActivity.java
+++ b/briar-android/src/org/briarproject/android/privategroup/conversation/GroupActivity.java
@@ -18,8 +18,9 @@ import android.view.MenuItem;
import org.briarproject.R;
import org.briarproject.android.ActivityComponent;
import org.briarproject.android.controller.handler.UiResultExceptionHandler;
-import org.briarproject.android.privategroup.memberlist.GroupMemberListActivity;
+import org.briarproject.android.privategroup.conversation.GroupController.GroupListener;
import org.briarproject.android.privategroup.creation.GroupInviteActivity;
+import org.briarproject.android.privategroup.memberlist.GroupMemberListActivity;
import org.briarproject.android.threaded.ThreadListActivity;
import org.briarproject.android.threaded.ThreadListController;
import org.briarproject.api.db.DbException;
@@ -29,11 +30,12 @@ import org.briarproject.api.privategroup.PrivateGroup;
import javax.inject.Inject;
import static android.support.v4.app.ActivityOptionsCompat.makeCustomAnimation;
+import static android.view.View.GONE;
import static org.briarproject.api.privategroup.PrivateGroupConstants.MAX_GROUP_POST_BODY_LENGTH;
public class GroupActivity extends
ThreadListActivity
- implements OnClickListener {
+ implements GroupListener, OnClickListener {
private final static int REQUEST_INVITE = 2;
@@ -200,6 +202,12 @@ public class GroupActivity extends
if (writeMenuItem != null) writeMenuItem.setVisible(enabled);
textInput.setSendButtonEnabled(enabled);
list.getRecyclerView().setAlpha(enabled ? 1f : 0.5f);
+
+ if (!enabled) {
+ textInput.setVisibility(GONE);
+ if (textInput.isKeyboardOpen()) textInput.hideSoftKeyboard();
+ if (textInput.isEmojiDrawerOpen()) textInput.hideEmojiDrawer();
+ }
}
private void showMenuItems() {
@@ -254,4 +262,15 @@ public class GroupActivity extends
});
}
+ @Override
+ public void onGroupDissolved() {
+ setGroupEnabled(false);
+ AlertDialog.Builder builder =
+ new AlertDialog.Builder(this, R.style.BriarDialogTheme);
+ builder.setTitle(getString(R.string.groups_dissolved_dialog_title));
+ builder.setMessage(getString(R.string.groups_dissolved_dialog_message));
+ builder.setNeutralButton(R.string.ok, null);
+ builder.show();
+ }
+
}
diff --git a/briar-android/src/org/briarproject/android/privategroup/conversation/GroupController.java b/briar-android/src/org/briarproject/android/privategroup/conversation/GroupController.java
index ffdc971fc..18915ab15 100644
--- a/briar-android/src/org/briarproject/android/privategroup/conversation/GroupController.java
+++ b/briar-android/src/org/briarproject/android/privategroup/conversation/GroupController.java
@@ -1,5 +1,7 @@
package org.briarproject.android.privategroup.conversation;
+import android.support.annotation.UiThread;
+
import org.briarproject.android.controller.handler.ResultExceptionHandler;
import org.briarproject.android.threaded.ThreadListController;
import org.briarproject.api.db.DbException;
@@ -16,4 +18,9 @@ public interface GroupController
void isDissolved(
ResultExceptionHandler handler);
+ interface GroupListener extends ThreadListListener {
+ @UiThread
+ void onGroupDissolved();
+ }
+
}
diff --git a/briar-android/src/org/briarproject/android/privategroup/conversation/GroupControllerImpl.java b/briar-android/src/org/briarproject/android/privategroup/conversation/GroupControllerImpl.java
index 8146f200a..89de80331 100644
--- a/briar-android/src/org/briarproject/android/privategroup/conversation/GroupControllerImpl.java
+++ b/briar-android/src/org/briarproject/android/privategroup/conversation/GroupControllerImpl.java
@@ -4,12 +4,14 @@ import android.support.annotation.Nullable;
import org.briarproject.android.api.AndroidNotificationManager;
import org.briarproject.android.controller.handler.ResultExceptionHandler;
+import org.briarproject.android.privategroup.conversation.GroupController.GroupListener;
import org.briarproject.android.threaded.ThreadListControllerImpl;
import org.briarproject.api.crypto.CryptoExecutor;
import org.briarproject.api.db.DatabaseExecutor;
import org.briarproject.api.db.DbException;
import org.briarproject.api.event.Event;
import org.briarproject.api.event.EventBus;
+import org.briarproject.api.event.GroupDissolvedEvent;
import org.briarproject.api.event.GroupMessageAddedEvent;
import org.briarproject.api.identity.IdentityManager;
import org.briarproject.api.identity.LocalAuthor;
@@ -34,7 +36,7 @@ import static java.lang.Math.max;
import static java.util.logging.Level.WARNING;
public class GroupControllerImpl extends
- ThreadListControllerImpl
+ ThreadListControllerImpl
implements GroupController {
private static final Logger LOG =
@@ -78,6 +80,16 @@ public class GroupControllerImpl extends
}
});
}
+ } else if (e instanceof GroupDissolvedEvent) {
+ GroupDissolvedEvent g = (GroupDissolvedEvent) e;
+ if (getGroupId().equals(g.getGroupId())) {
+ listener.runOnUiThreadUnlessDestroyed(new Runnable() {
+ @Override
+ public void run() {
+ listener.onGroupDissolved();
+ }
+ });
+ }
}
}
diff --git a/briar-android/src/org/briarproject/android/privategroup/list/GroupItem.java b/briar-android/src/org/briarproject/android/privategroup/list/GroupItem.java
index ac75f29cd..31c6458a6 100644
--- a/briar-android/src/org/briarproject/android/privategroup/list/GroupItem.java
+++ b/briar-android/src/org/briarproject/android/privategroup/list/GroupItem.java
@@ -70,4 +70,8 @@ class GroupItem {
return dissolved;
}
+ void setDissolved() {
+ dissolved = true;
+ }
+
}
diff --git a/briar-android/src/org/briarproject/android/privategroup/list/GroupListController.java b/briar-android/src/org/briarproject/android/privategroup/list/GroupListController.java
index f102f82e4..71c9f8305 100644
--- a/briar-android/src/org/briarproject/android/privategroup/list/GroupListController.java
+++ b/briar-android/src/org/briarproject/android/privategroup/list/GroupListController.java
@@ -38,11 +38,18 @@ public interface GroupListController extends DbController {
@UiThread
void onGroupMessageAdded(GroupMessageHeader header);
+ @UiThread
+ void onGroupInvitationReceived();
+
@UiThread
void onGroupAdded(GroupId groupId);
@UiThread
void onGroupRemoved(GroupId groupId);
+
+ @UiThread
+ void onGroupDissolved(GroupId groupId);
+
}
}
diff --git a/briar-android/src/org/briarproject/android/privategroup/list/GroupListControllerImpl.java b/briar-android/src/org/briarproject/android/privategroup/list/GroupListControllerImpl.java
index 4524e484b..60881e1c8 100644
--- a/briar-android/src/org/briarproject/android/privategroup/list/GroupListControllerImpl.java
+++ b/briar-android/src/org/briarproject/android/privategroup/list/GroupListControllerImpl.java
@@ -13,6 +13,8 @@ import org.briarproject.api.event.Event;
import org.briarproject.api.event.EventBus;
import org.briarproject.api.event.EventListener;
import org.briarproject.api.event.GroupAddedEvent;
+import org.briarproject.api.event.GroupDissolvedEvent;
+import org.briarproject.api.event.GroupInvitationReceivedEvent;
import org.briarproject.api.event.GroupMessageAddedEvent;
import org.briarproject.api.event.GroupRemovedEvent;
import org.briarproject.api.lifecycle.LifecycleManager;
@@ -89,6 +91,10 @@ public class GroupListControllerImpl extends DbControllerImpl
GroupMessageAddedEvent g = (GroupMessageAddedEvent) e;
LOG.info("Private group message added");
onGroupMessageAdded(g.getHeader());
+ } else if (e instanceof GroupInvitationReceivedEvent) {
+ GroupInvitationReceivedEvent g = (GroupInvitationReceivedEvent) e;
+ LOG.info("Private group invitation received");
+ onGroupInvitationReceived();
} else if (e instanceof GroupAddedEvent) {
GroupAddedEvent g = (GroupAddedEvent) e;
ClientId id = g.getGroup().getClientId();
@@ -103,6 +109,10 @@ public class GroupListControllerImpl extends DbControllerImpl
LOG.info("Private group removed");
onGroupRemoved(g.getGroup().getId());
}
+ } else if (e instanceof GroupDissolvedEvent) {
+ GroupDissolvedEvent g = (GroupDissolvedEvent) e;
+ LOG.info("Private group dissolved");
+ onGroupDissolved(g.getGroupId());
}
}
@@ -115,6 +125,15 @@ public class GroupListControllerImpl extends DbControllerImpl
});
}
+ private void onGroupInvitationReceived() {
+ listener.runOnUiThreadUnlessDestroyed(new Runnable() {
+ @Override
+ public void run() {
+ listener.onGroupInvitationReceived();
+ }
+ });
+ }
+
private void onGroupAdded(final GroupId g) {
listener.runOnUiThreadUnlessDestroyed(new Runnable() {
@Override
@@ -133,6 +152,15 @@ public class GroupListControllerImpl extends DbControllerImpl
});
}
+ private void onGroupDissolved(final GroupId g) {
+ listener.runOnUiThreadUnlessDestroyed(new Runnable() {
+ @Override
+ public void run() {
+ listener.onGroupDissolved(g);
+ }
+ });
+ }
+
@Override
public void loadGroups(
final ResultExceptionHandler, DbException> handler) {
diff --git a/briar-android/src/org/briarproject/android/privategroup/list/GroupListFragment.java b/briar-android/src/org/briarproject/android/privategroup/list/GroupListFragment.java
index ec9f94b9f..6dbcf3149 100644
--- a/briar-android/src/org/briarproject/android/privategroup/list/GroupListFragment.java
+++ b/briar-android/src/org/briarproject/android/privategroup/list/GroupListFragment.java
@@ -151,6 +151,11 @@ public class GroupListFragment extends BaseFragment implements
}
}
+ @Override
+ public void onGroupInvitationReceived() {
+ loadAvailableGroups();
+ }
+
@UiThread
@Override
public void onGroupAdded(GroupId groupId) {
@@ -164,6 +169,17 @@ public class GroupListFragment extends BaseFragment implements
adapter.removeItem(groupId);
}
+ @Override
+ public void onGroupDissolved(GroupId groupId) {
+ adapter.incrementRevision();
+ int position = adapter.findItemPosition(groupId);
+ GroupItem item = adapter.getItemAt(position);
+ if (item != null) {
+ item.setDissolved();
+ adapter.updateItemAt(position, item);
+ }
+ }
+
@Override
public String getUniqueTag() {
return TAG;
diff --git a/briar-android/src/org/briarproject/android/threaded/ThreadListControllerImpl.java b/briar-android/src/org/briarproject/android/threaded/ThreadListControllerImpl.java
index 441758258..3d52c972f 100644
--- a/briar-android/src/org/briarproject/android/threaded/ThreadListControllerImpl.java
+++ b/briar-android/src/org/briarproject/android/threaded/ThreadListControllerImpl.java
@@ -6,6 +6,7 @@ import android.support.annotation.CallSuper;
import org.briarproject.android.api.AndroidNotificationManager;
import org.briarproject.android.controller.DbControllerImpl;
import org.briarproject.android.controller.handler.ResultExceptionHandler;
+import org.briarproject.android.threaded.ThreadListController.ThreadListListener;
import org.briarproject.api.clients.ThreadedMessage;
import org.briarproject.api.clients.NamedGroup;
import org.briarproject.api.clients.PostHeader;
@@ -34,7 +35,7 @@ import java.util.logging.Logger;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
-public abstract class ThreadListControllerImpl
+public abstract class ThreadListControllerImpl>
extends DbControllerImpl
implements ThreadListController, EventListener {
@@ -49,7 +50,7 @@ public abstract class ThreadListControllerImpl listener;
+ protected volatile L listener;
protected ThreadListControllerImpl(@DatabaseExecutor Executor dbExecutor,
LifecycleManager lifecycleManager, IdentityManager identityManager,
@@ -72,7 +73,7 @@ public abstract class ThreadListControllerImpl) activity;
+ listener = (L) activity;
}
@CallSuper
diff --git a/briar-api/src/org/briarproject/api/event/GroupDissolvedEvent.java b/briar-api/src/org/briarproject/api/event/GroupDissolvedEvent.java
new file mode 100644
index 000000000..5b8a3224d
--- /dev/null
+++ b/briar-api/src/org/briarproject/api/event/GroupDissolvedEvent.java
@@ -0,0 +1,26 @@
+package org.briarproject.api.event;
+
+import org.briarproject.api.nullsafety.NotNullByDefault;
+import org.briarproject.api.sync.GroupId;
+
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * An event that is broadcast when a private group was dissolved
+ * by a remote creator.
+ */
+@Immutable
+@NotNullByDefault
+public class GroupDissolvedEvent extends Event {
+
+ private final GroupId groupId;
+
+ public GroupDissolvedEvent(GroupId groupId) {
+ this.groupId = groupId;
+ }
+
+ public GroupId getGroupId() {
+ return groupId;
+ }
+
+}
diff --git a/briar-core/src/org/briarproject/privategroup/PrivateGroupManagerImpl.java b/briar-core/src/org/briarproject/privategroup/PrivateGroupManagerImpl.java
index 4b2ab0266..2865aa938 100644
--- a/briar-core/src/org/briarproject/privategroup/PrivateGroupManagerImpl.java
+++ b/briar-core/src/org/briarproject/privategroup/PrivateGroupManagerImpl.java
@@ -10,6 +10,8 @@ import org.briarproject.api.data.MetadataParser;
import org.briarproject.api.db.DatabaseComponent;
import org.briarproject.api.db.DbException;
import org.briarproject.api.db.Transaction;
+import org.briarproject.api.event.Event;
+import org.briarproject.api.event.GroupDissolvedEvent;
import org.briarproject.api.identity.Author;
import org.briarproject.api.identity.Author.Status;
import org.briarproject.api.identity.AuthorId;
@@ -176,6 +178,8 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
} catch (FormatException e) {
throw new DbException(e);
}
+ Event e = new GroupDissolvedEvent(g);
+ txn.attach(e);
}
@Override