Create GroupDissolvedEvent and react to it

Also react to incoming group invitations
This commit is contained in:
Torsten Grote
2016-11-07 16:09:07 -02:00
parent 1809943f1d
commit 62040d45b8
12 changed files with 139 additions and 12 deletions

View File

@@ -155,7 +155,7 @@
<item quantity="other">%d messages</item> <item quantity="other">%d messages</item>
</plurals> </plurals>
<string name="groups_group_is_empty">This group is empty</string> <string name="groups_group_is_empty">This group is empty</string>
<string name="groups_group_is_dissolved">This group is dissolved</string> <string name="groups_group_is_dissolved">This group has been dissolved</string>
<string name="groups_remove">Remove</string> <string name="groups_remove">Remove</string>
<string name="groups_create_group_title">Create Private Group</string> <string name="groups_create_group_title">Create Private Group</string>
<string name="groups_no_messages">This group is empty.\n\nYou can use the pen icon at the top to compose the first message.</string> <string name="groups_no_messages">This group is empty.\n\nYou can use the pen icon at the top to compose the first message.</string>
@@ -168,11 +168,16 @@
<string name="groups_message_received">Message received</string> <string name="groups_message_received">Message received</string>
<string name="groups_member_list">Member List</string> <string name="groups_member_list">Member List</string>
<string name="groups_invite_members">Invite Members</string> <string name="groups_invite_members">Invite Members</string>
<string name="groups_member_joined">joined the group.</string>
<string name="groups_leave">Leave Group</string> <string name="groups_leave">Leave Group</string>
<string name="groups_leave_dialog_title">Confirm Leaving Group</string> <string name="groups_leave_dialog_title">Confirm Leaving Group</string>
<string name="groups_leave_dialog_message">Are you sure that you want to leave this group?</string> <string name="groups_leave_dialog_message">Are you sure that you want to leave this group?</string>
<string name="groups_dissolve">Dissolve Group</string> <string name="groups_dissolve">Dissolve Group</string>
<string name="groups_member_joined">joined the group.</string> <string name="groups_dissolve_dialog_title">Confirm Dissolving Group</string>
<string name="groups_dissolve_dialog_message">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.</string>
<string name="groups_dissolve_button">Dissolve</string>
<string name="groups_dissolved_dialog_title">Group Has Been Dissolved</string>
<string name="groups_dissolved_dialog_message">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.</string>
<!-- Private Group Invitations --> <!-- Private Group Invitations -->
<string name="groups_invitations_title">Group Invitations</string> <string name="groups_invitations_title">Group Invitations</string>
@@ -188,9 +193,6 @@
<string name="groups_invitations_response_declined_sent">You declined the group invitation from %s.</string> <string name="groups_invitations_response_declined_sent">You declined the group invitation from %s.</string>
<string name="groups_invitations_response_accepted_received">%s accepted your group invitation.</string> <string name="groups_invitations_response_accepted_received">%s accepted your group invitation.</string>
<string name="groups_invitations_response_declined_received">%s declined your group invitation.</string> <string name="groups_invitations_response_declined_received">%s declined your group invitation.</string>
<string name="groups_dissolve_dialog_title">Confirm Dissolving Group</string>
<string name="groups_dissolve_dialog_message">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.</string>
<string name="groups_dissolve_button">Dissolve</string>
<!-- Forums --> <!-- Forums -->
<string name="no_forums">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.</string> <string name="no_forums">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.</string>

View File

@@ -4,6 +4,7 @@ import android.support.annotation.Nullable;
import org.briarproject.android.api.AndroidNotificationManager; import org.briarproject.android.api.AndroidNotificationManager;
import org.briarproject.android.controller.handler.ResultExceptionHandler; import org.briarproject.android.controller.handler.ResultExceptionHandler;
import org.briarproject.android.threaded.ThreadListController.ThreadListListener;
import org.briarproject.android.threaded.ThreadListControllerImpl; import org.briarproject.android.threaded.ThreadListControllerImpl;
import org.briarproject.api.clients.MessageTracker.GroupCount; import org.briarproject.api.clients.MessageTracker.GroupCount;
import org.briarproject.api.crypto.CryptoExecutor; import org.briarproject.api.crypto.CryptoExecutor;
@@ -32,7 +33,7 @@ import static java.lang.Math.max;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
public class ForumControllerImpl public class ForumControllerImpl
extends ThreadListControllerImpl<Forum, ForumItem, ForumPostHeader, ForumPost> extends ThreadListControllerImpl<Forum, ForumItem, ForumPostHeader, ForumPost, ThreadListListener<ForumPostHeader>>
implements ForumController { implements ForumController {
private static final Logger LOG = private static final Logger LOG =

View File

@@ -18,8 +18,9 @@ import android.view.MenuItem;
import org.briarproject.R; import org.briarproject.R;
import org.briarproject.android.ActivityComponent; import org.briarproject.android.ActivityComponent;
import org.briarproject.android.controller.handler.UiResultExceptionHandler; 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.creation.GroupInviteActivity;
import org.briarproject.android.privategroup.memberlist.GroupMemberListActivity;
import org.briarproject.android.threaded.ThreadListActivity; import org.briarproject.android.threaded.ThreadListActivity;
import org.briarproject.android.threaded.ThreadListController; import org.briarproject.android.threaded.ThreadListController;
import org.briarproject.api.db.DbException; import org.briarproject.api.db.DbException;
@@ -29,11 +30,12 @@ import org.briarproject.api.privategroup.PrivateGroup;
import javax.inject.Inject; import javax.inject.Inject;
import static android.support.v4.app.ActivityOptionsCompat.makeCustomAnimation; 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; import static org.briarproject.api.privategroup.PrivateGroupConstants.MAX_GROUP_POST_BODY_LENGTH;
public class GroupActivity extends public class GroupActivity extends
ThreadListActivity<PrivateGroup, GroupMessageItem, GroupMessageHeader> ThreadListActivity<PrivateGroup, GroupMessageItem, GroupMessageHeader>
implements OnClickListener { implements GroupListener, OnClickListener {
private final static int REQUEST_INVITE = 2; private final static int REQUEST_INVITE = 2;
@@ -200,6 +202,12 @@ public class GroupActivity extends
if (writeMenuItem != null) writeMenuItem.setVisible(enabled); if (writeMenuItem != null) writeMenuItem.setVisible(enabled);
textInput.setSendButtonEnabled(enabled); textInput.setSendButtonEnabled(enabled);
list.getRecyclerView().setAlpha(enabled ? 1f : 0.5f); 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() { 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();
}
} }

View File

@@ -1,5 +1,7 @@
package org.briarproject.android.privategroup.conversation; package org.briarproject.android.privategroup.conversation;
import android.support.annotation.UiThread;
import org.briarproject.android.controller.handler.ResultExceptionHandler; import org.briarproject.android.controller.handler.ResultExceptionHandler;
import org.briarproject.android.threaded.ThreadListController; import org.briarproject.android.threaded.ThreadListController;
import org.briarproject.api.db.DbException; import org.briarproject.api.db.DbException;
@@ -16,4 +18,9 @@ public interface GroupController
void isDissolved( void isDissolved(
ResultExceptionHandler<Boolean, DbException> handler); ResultExceptionHandler<Boolean, DbException> handler);
interface GroupListener extends ThreadListListener<GroupMessageHeader> {
@UiThread
void onGroupDissolved();
}
} }

View File

@@ -4,12 +4,14 @@ import android.support.annotation.Nullable;
import org.briarproject.android.api.AndroidNotificationManager; import org.briarproject.android.api.AndroidNotificationManager;
import org.briarproject.android.controller.handler.ResultExceptionHandler; import org.briarproject.android.controller.handler.ResultExceptionHandler;
import org.briarproject.android.privategroup.conversation.GroupController.GroupListener;
import org.briarproject.android.threaded.ThreadListControllerImpl; import org.briarproject.android.threaded.ThreadListControllerImpl;
import org.briarproject.api.crypto.CryptoExecutor; import org.briarproject.api.crypto.CryptoExecutor;
import org.briarproject.api.db.DatabaseExecutor; import org.briarproject.api.db.DatabaseExecutor;
import org.briarproject.api.db.DbException; import org.briarproject.api.db.DbException;
import org.briarproject.api.event.Event; import org.briarproject.api.event.Event;
import org.briarproject.api.event.EventBus; import org.briarproject.api.event.EventBus;
import org.briarproject.api.event.GroupDissolvedEvent;
import org.briarproject.api.event.GroupMessageAddedEvent; import org.briarproject.api.event.GroupMessageAddedEvent;
import org.briarproject.api.identity.IdentityManager; import org.briarproject.api.identity.IdentityManager;
import org.briarproject.api.identity.LocalAuthor; import org.briarproject.api.identity.LocalAuthor;
@@ -34,7 +36,7 @@ import static java.lang.Math.max;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
public class GroupControllerImpl extends public class GroupControllerImpl extends
ThreadListControllerImpl<PrivateGroup, GroupMessageItem, GroupMessageHeader, GroupMessage> ThreadListControllerImpl<PrivateGroup, GroupMessageItem, GroupMessageHeader, GroupMessage, GroupListener>
implements GroupController { implements GroupController {
private static final Logger LOG = 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();
}
});
}
} }
} }

View File

@@ -70,4 +70,8 @@ class GroupItem {
return dissolved; return dissolved;
} }
void setDissolved() {
dissolved = true;
}
} }

View File

@@ -38,11 +38,18 @@ public interface GroupListController extends DbController {
@UiThread @UiThread
void onGroupMessageAdded(GroupMessageHeader header); void onGroupMessageAdded(GroupMessageHeader header);
@UiThread
void onGroupInvitationReceived();
@UiThread @UiThread
void onGroupAdded(GroupId groupId); void onGroupAdded(GroupId groupId);
@UiThread @UiThread
void onGroupRemoved(GroupId groupId); void onGroupRemoved(GroupId groupId);
@UiThread
void onGroupDissolved(GroupId groupId);
} }
} }

View File

@@ -13,6 +13,8 @@ import org.briarproject.api.event.Event;
import org.briarproject.api.event.EventBus; import org.briarproject.api.event.EventBus;
import org.briarproject.api.event.EventListener; import org.briarproject.api.event.EventListener;
import org.briarproject.api.event.GroupAddedEvent; 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.GroupMessageAddedEvent;
import org.briarproject.api.event.GroupRemovedEvent; import org.briarproject.api.event.GroupRemovedEvent;
import org.briarproject.api.lifecycle.LifecycleManager; import org.briarproject.api.lifecycle.LifecycleManager;
@@ -89,6 +91,10 @@ public class GroupListControllerImpl extends DbControllerImpl
GroupMessageAddedEvent g = (GroupMessageAddedEvent) e; GroupMessageAddedEvent g = (GroupMessageAddedEvent) e;
LOG.info("Private group message added"); LOG.info("Private group message added");
onGroupMessageAdded(g.getHeader()); onGroupMessageAdded(g.getHeader());
} else if (e instanceof GroupInvitationReceivedEvent) {
GroupInvitationReceivedEvent g = (GroupInvitationReceivedEvent) e;
LOG.info("Private group invitation received");
onGroupInvitationReceived();
} else if (e instanceof GroupAddedEvent) { } else if (e instanceof GroupAddedEvent) {
GroupAddedEvent g = (GroupAddedEvent) e; GroupAddedEvent g = (GroupAddedEvent) e;
ClientId id = g.getGroup().getClientId(); ClientId id = g.getGroup().getClientId();
@@ -103,6 +109,10 @@ public class GroupListControllerImpl extends DbControllerImpl
LOG.info("Private group removed"); LOG.info("Private group removed");
onGroupRemoved(g.getGroup().getId()); 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) { private void onGroupAdded(final GroupId g) {
listener.runOnUiThreadUnlessDestroyed(new Runnable() { listener.runOnUiThreadUnlessDestroyed(new Runnable() {
@Override @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 @Override
public void loadGroups( public void loadGroups(
final ResultExceptionHandler<Collection<GroupItem>, DbException> handler) { final ResultExceptionHandler<Collection<GroupItem>, DbException> handler) {

View File

@@ -151,6 +151,11 @@ public class GroupListFragment extends BaseFragment implements
} }
} }
@Override
public void onGroupInvitationReceived() {
loadAvailableGroups();
}
@UiThread @UiThread
@Override @Override
public void onGroupAdded(GroupId groupId) { public void onGroupAdded(GroupId groupId) {
@@ -164,6 +169,17 @@ public class GroupListFragment extends BaseFragment implements
adapter.removeItem(groupId); 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 @Override
public String getUniqueTag() { public String getUniqueTag() {
return TAG; return TAG;

View File

@@ -6,6 +6,7 @@ import android.support.annotation.CallSuper;
import org.briarproject.android.api.AndroidNotificationManager; import org.briarproject.android.api.AndroidNotificationManager;
import org.briarproject.android.controller.DbControllerImpl; import org.briarproject.android.controller.DbControllerImpl;
import org.briarproject.android.controller.handler.ResultExceptionHandler; 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.ThreadedMessage;
import org.briarproject.api.clients.NamedGroup; import org.briarproject.api.clients.NamedGroup;
import org.briarproject.api.clients.PostHeader; 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.INFO;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
public abstract class ThreadListControllerImpl<G extends NamedGroup, I extends ThreadItem, H extends PostHeader, M extends ThreadedMessage> public abstract class ThreadListControllerImpl<G extends NamedGroup, I extends ThreadItem, H extends PostHeader, M extends ThreadedMessage, L extends ThreadListListener<H>>
extends DbControllerImpl extends DbControllerImpl
implements ThreadListController<G, I, H>, EventListener { implements ThreadListController<G, I, H>, EventListener {
@@ -49,7 +50,7 @@ public abstract class ThreadListControllerImpl<G extends NamedGroup, I extends T
protected final AndroidNotificationManager notificationManager; protected final AndroidNotificationManager notificationManager;
protected final Executor cryptoExecutor; protected final Executor cryptoExecutor;
protected final Clock clock; protected final Clock clock;
protected volatile ThreadListListener<H> listener; protected volatile L listener;
protected ThreadListControllerImpl(@DatabaseExecutor Executor dbExecutor, protected ThreadListControllerImpl(@DatabaseExecutor Executor dbExecutor,
LifecycleManager lifecycleManager, IdentityManager identityManager, LifecycleManager lifecycleManager, IdentityManager identityManager,
@@ -72,7 +73,7 @@ public abstract class ThreadListControllerImpl<G extends NamedGroup, I extends T
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public void onActivityCreate(Activity activity) { public void onActivityCreate(Activity activity) {
listener = (ThreadListListener<H>) activity; listener = (L) activity;
} }
@CallSuper @CallSuper

View File

@@ -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;
}
}

View File

@@ -10,6 +10,8 @@ import org.briarproject.api.data.MetadataParser;
import org.briarproject.api.db.DatabaseComponent; import org.briarproject.api.db.DatabaseComponent;
import org.briarproject.api.db.DbException; import org.briarproject.api.db.DbException;
import org.briarproject.api.db.Transaction; 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;
import org.briarproject.api.identity.Author.Status; import org.briarproject.api.identity.Author.Status;
import org.briarproject.api.identity.AuthorId; import org.briarproject.api.identity.AuthorId;
@@ -176,6 +178,8 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
} catch (FormatException e) { } catch (FormatException e) {
throw new DbException(e); throw new DbException(e);
} }
Event e = new GroupDissolvedEvent(g);
txn.attach(e);
} }
@Override @Override