Merge branch '671-implement-ux-for-leaving-a-group' into 'master'

Implement UX for leaving a group

This MR also includes the creator's part of the UX for dissolving a group since it is almost the same.

![device-2016-10-26-185615](/uploads/8689a1ee103fcee23105a469b37c59de/device-2016-10-26-185615.png)

Closes #671

See merge request !367
This commit is contained in:
akwizgran
2016-11-01 10:57:33 +00:00
8 changed files with 125 additions and 15 deletions

View File

@@ -25,15 +25,12 @@
<item
android:id="@+id/action_group_leave"
android:enabled="false"
android:icon="@drawable/action_delete_white"
android:title="@string/groups_leave"
android:visible="false"
app:showAsAction="never"/>
<item
android:id="@+id/action_group_dissolve"
android:enabled="false"
android:icon="@drawable/action_delete_white"
android:title="@string/groups_dissolve"
app:showAsAction="never"/>

View File

@@ -163,6 +163,8 @@
<string name="groups_member_list">Member List</string>
<string name="groups_invite_members">Invite Members</string>
<string name="groups_leave">Leave 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_dissolve">Dissolve Group</string>
<string name="groups_member_joined">joined the group.</string>
@@ -180,6 +182,9 @@
<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_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 -->
<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

@@ -149,11 +149,11 @@ public class ForumActivity extends
OnClickListener okListener = new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
deleteNamedGroup();
deleteForum();
}
};
AlertDialog.Builder builder = new AlertDialog.Builder(
ForumActivity.this, R.style.BriarDialogTheme);
AlertDialog.Builder builder = new AlertDialog.Builder(this,
R.style.BriarDialogTheme);
builder.setTitle(getString(R.string.dialog_title_leave_forum));
builder.setMessage(getString(R.string.dialog_message_leave_forum));
builder.setNegativeButton(R.string.dialog_button_leave, okListener);
@@ -161,7 +161,7 @@ public class ForumActivity extends
builder.show();
}
private void deleteNamedGroup() {
private void deleteForum() {
forumController.deleteNamedGroup(
new UiResultExceptionHandler<Void, DbException>(this) {
@Override

View File

@@ -1,10 +1,13 @@
package org.briarproject.android.privategroup.conversation;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.LayoutRes;
import android.support.annotation.StringRes;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.LinearLayoutManager;
import android.view.Menu;
import android.view.MenuInflater;
@@ -12,8 +15,10 @@ import android.view.MenuItem;
import org.briarproject.R;
import org.briarproject.android.ActivityComponent;
import org.briarproject.android.controller.handler.UiResultExceptionHandler;
import org.briarproject.android.threaded.ThreadListActivity;
import org.briarproject.android.threaded.ThreadListController;
import org.briarproject.api.db.DbException;
import org.briarproject.api.privategroup.GroupMessageHeader;
import org.briarproject.api.privategroup.PrivateGroup;
@@ -22,11 +27,16 @@ import javax.inject.Inject;
import static org.briarproject.api.privategroup.PrivateGroupConstants.MAX_GROUP_POST_BODY_LENGTH;
public class GroupActivity extends
ThreadListActivity<PrivateGroup, GroupMessageItem, GroupMessageHeader> {
ThreadListActivity<PrivateGroup, GroupMessageItem, GroupMessageHeader>
implements OnClickListener {
@Inject
GroupController controller;
private boolean isCreator;
private MenuItem leaveMenuItem;
private MenuItem dissolveMenuItem;
@Override
public void injectActivity(ActivityComponent component) {
component.inject(this);
@@ -58,6 +68,20 @@ public class GroupActivity extends
actionBar.setSubtitle(getString(R.string.groups_created_by,
group.getAuthor().getName()));
}
controller.isCreator(group,
new UiResultExceptionHandler<Boolean, DbException>(this) {
@Override
public void onResultUi(Boolean isCreator) {
GroupActivity.this.isCreator = isCreator;
showMenuItems();
}
@Override
public void onExceptionUi(DbException exception) {
// TODO proper error handling
finish();
}
});
}
@Override
@@ -78,6 +102,10 @@ public class GroupActivity extends
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.group_actions, menu);
leaveMenuItem = menu.findItem(R.id.action_group_leave);
dissolveMenuItem = menu.findItem(R.id.action_group_dissolve);
showMenuItems();
return super.onCreateOptionsMenu(menu);
}
@@ -87,6 +115,12 @@ public class GroupActivity extends
case R.id.action_group_compose_message:
showTextInput(null);
return true;
case R.id.action_group_leave:
showLeaveGroupDialog();
return true;
case R.id.action_group_dissolve:
showDissolveGroupDialog();
return true;
default:
return super.onOptionsItemSelected(item);
}
@@ -109,4 +143,53 @@ public class GroupActivity extends
return R.string.groups_message_received;
}
private void showMenuItems() {
if (leaveMenuItem == null || dissolveMenuItem == null) return;
if (isCreator) {
leaveMenuItem.setVisible(false);
dissolveMenuItem.setVisible(true);
} else {
leaveMenuItem.setVisible(true);
dissolveMenuItem.setVisible(false);
}
}
private void showLeaveGroupDialog() {
AlertDialog.Builder builder =
new AlertDialog.Builder(this, R.style.BriarDialogTheme);
builder.setTitle(getString(R.string.groups_leave_dialog_title));
builder.setMessage(getString(R.string.groups_leave_dialog_message));
builder.setNegativeButton(R.string.dialog_button_leave, this);
builder.setPositiveButton(R.string.cancel, null);
builder.show();
}
private void showDissolveGroupDialog() {
AlertDialog.Builder builder =
new AlertDialog.Builder(this, R.style.BriarDialogTheme);
builder.setTitle(getString(R.string.groups_dissolve_dialog_title));
builder.setMessage(getString(R.string.groups_dissolve_dialog_message));
builder.setNegativeButton(R.string.groups_dissolve_button, this);
builder.setPositiveButton(R.string.cancel, null);
builder.show();
}
@Override
public void onClick(DialogInterface dialog, int which) {
controller.deleteNamedGroup(
new UiResultExceptionHandler<Void, DbException>(this) {
@Override
public void onResultUi(Void v) {
// The activity is going to be destroyed by the
// GroupRemovedEvent being fired
}
@Override
public void onExceptionUi(DbException exception) {
// TODO proper error handling
finish();
}
});
}
}

View File

@@ -1,6 +1,8 @@
package org.briarproject.android.privategroup.conversation;
import org.briarproject.android.controller.handler.ResultExceptionHandler;
import org.briarproject.android.threaded.ThreadListController;
import org.briarproject.api.db.DbException;
import org.briarproject.api.privategroup.GroupMessageHeader;
import org.briarproject.api.privategroup.PrivateGroup;
@@ -8,4 +10,7 @@ public interface GroupController
extends
ThreadListController<PrivateGroup, GroupMessageItem, GroupMessageHeader> {
void isCreator(PrivateGroup group,
ResultExceptionHandler<Boolean, DbException> handler);
}

View File

@@ -30,6 +30,7 @@ import java.util.logging.Logger;
import javax.inject.Inject;
import static java.lang.Math.max;
import static java.util.logging.Level.WARNING;
public class GroupControllerImpl extends
@@ -174,4 +175,24 @@ public class GroupControllerImpl extends
return new GroupMessageItem(header, body);
}
@Override
public void isCreator(final PrivateGroup group,
final ResultExceptionHandler<Boolean, DbException> handler) {
runOnDbThread(new Runnable() {
@Override
public void run() {
try {
LocalAuthor author = identityManager.getLocalAuthor();
boolean isCreator =
author.getId().equals(group.getAuthor().getId());
handler.onResult(isCreator);
} catch (DbException e) {
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
handler.onException(e);
}
}
});
}
}

View File

@@ -41,16 +41,14 @@ public abstract class ThreadListControllerImpl<G extends NamedGroup, I extends T
private static final Logger LOG =
Logger.getLogger(ThreadListControllerImpl.class.getName());
protected final IdentityManager identityManager;
protected final Executor cryptoExecutor;
protected final AndroidNotificationManager notificationManager;
protected final Clock clock;
private final EventBus eventBus;
private final Map<MessageId, String> bodyCache = new ConcurrentHashMap<>();
private volatile GroupId groupId;
protected final IdentityManager identityManager;
protected final AndroidNotificationManager notificationManager;
protected final Executor cryptoExecutor;
protected final Clock clock;
protected volatile ThreadListListener<H> listener;
protected ThreadListControllerImpl(@DatabaseExecutor Executor dbExecutor,

View File

@@ -138,12 +138,13 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
@Override
public void removePrivateGroup(GroupId g) throws DbException {
// TODO
Transaction txn = db.startTransaction(false);
try {
for (PrivateGroupHook hook : hooks) {
hook.removingGroup(txn, g);
}
Group group = db.getGroup(txn, g);
db.removeGroup(txn, group);
txn.setComplete();
} finally {
db.endTransaction(txn);