Show group invitations in group list

This commit is contained in:
Torsten Grote
2016-10-17 13:49:04 -02:00
parent a92f7e1c9f
commit 96666273d3
14 changed files with 304 additions and 4 deletions

View File

@@ -122,6 +122,16 @@
/>
</activity>
<activity
android:name=".android.privategroup.invitation.InvitationsGroupActivity"
android:label="@string/groups_invitations_title"
android:parentActivityName=".android.NavDrawerActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".android.NavDrawerActivity"
/>
</activity>
<activity
android:name=".android.sharing.InvitationsForumActivity"
android:label="@string/forum_invitations_title"

View File

@@ -168,6 +168,15 @@
<string name="groups_leave">Leave Group</string>
<string name="groups_dissolve">Dissolve Group</string>
<!-- Private Group Invitations -->
<string name="groups_invitations_title">Group Invitations</string>
<string name="groups_invitations_joined">Joined Group</string>
<string name="groups_invitations_declined">Group Invitation Declined</string>
<plurals name="groups_invitations_open">
<item quantity="one">%d open group invitation</item>
<item quantity="other">%d open group invitations</item>
</plurals>
<!-- 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="create_forum_title">New Forum</string>

View File

@@ -33,6 +33,7 @@ import org.briarproject.android.privategroup.creation.CreateGroupFragment;
import org.briarproject.android.privategroup.conversation.GroupActivity;
import org.briarproject.android.privategroup.creation.CreateGroupMessageFragment;
import org.briarproject.android.privategroup.list.GroupListFragment;
import org.briarproject.android.privategroup.invitation.InvitationsGroupActivity;
import org.briarproject.android.sharing.ContactSelectorFragment;
import org.briarproject.android.sharing.InvitationsBlogActivity;
import org.briarproject.android.sharing.InvitationsForumActivity;
@@ -77,8 +78,8 @@ public interface ActivityComponent {
void inject(InvitationsBlogActivity activity);
void inject(CreateGroupActivity activity);
void inject(GroupActivity activity);
void inject(InvitationsGroupActivity activity);
void inject(CreateForumActivity activity);

View File

@@ -25,6 +25,8 @@ import org.briarproject.android.privategroup.conversation.GroupController;
import org.briarproject.android.privategroup.conversation.GroupControllerImpl;
import org.briarproject.android.privategroup.creation.CreateGroupController;
import org.briarproject.android.privategroup.creation.CreateGroupControllerImpl;
import org.briarproject.android.privategroup.invitation.InvitationsGroupController;
import org.briarproject.android.privategroup.invitation.InvitationsGroupControllerImpl;
import org.briarproject.android.privategroup.list.GroupListController;
import org.briarproject.android.privategroup.list.GroupListControllerImpl;
import org.briarproject.android.sharing.InvitationsBlogController;
@@ -121,6 +123,13 @@ public class ActivityModule {
return groupController;
}
@ActivityScope
@Provides
protected InvitationsGroupController provideInvitationsGroupController(
InvitationsGroupControllerImpl invitationsGroupController) {
return invitationsGroupController;
}
@ActivityScope
@Provides
protected ForumController provideForumController(

View File

@@ -35,6 +35,7 @@ import org.briarproject.api.messaging.PrivateMessageFactory;
import org.briarproject.api.plugins.ConnectionRegistry;
import org.briarproject.api.plugins.PluginManager;
import org.briarproject.api.privategroup.PrivateGroupManager;
import org.briarproject.api.privategroup.invitation.GroupInvitationManager;
import org.briarproject.api.settings.SettingsManager;
import org.briarproject.api.system.Clock;
import org.briarproject.plugins.AndroidPluginsModule;
@@ -96,6 +97,8 @@ public interface AndroidComponent extends CoreEagerSingletons {
PrivateGroupManager privateGroupManager();
GroupInvitationManager groupInvitationManager();
ForumManager forumManager();
ForumSharingManager forumSharingManager();

View File

@@ -220,10 +220,10 @@ public class ForumListFragment extends BaseEventFragment implements
if (availableCount == 0) {
snackbar.dismiss();
} else {
snackbar.show();
snackbar.setText(getResources().getQuantityString(
R.plurals.forums_shared, availableCount,
availableCount));
if (!snackbar.isShownOrQueued()) snackbar.show();
}
}
});

View File

@@ -0,0 +1,28 @@
package org.briarproject.android.privategroup.invitation;
import android.support.annotation.Nullable;
import android.view.View;
import org.briarproject.R;
import org.briarproject.android.sharing.InvitationAdapter.InvitationClickListener;
import org.briarproject.android.sharing.InvitationViewHolder;
import org.briarproject.api.privategroup.invitation.GroupInvitationItem;
public class GroupInvitationViewHolder extends InvitationViewHolder<GroupInvitationItem> {
public GroupInvitationViewHolder(View v) {
super(v);
}
@Override
public void onBind(@Nullable final GroupInvitationItem item,
final InvitationClickListener<GroupInvitationItem> listener) {
super.onBind(item, listener);
if (item == null) return;
sharedBy.setText(
sharedBy.getContext().getString(R.string.groups_created_by,
item.getCreator().getAuthor().getName()));
}
}

View File

@@ -0,0 +1,28 @@
package org.briarproject.android.privategroup.invitation;
import android.content.Context;
import android.view.ViewGroup;
import org.briarproject.android.sharing.InvitationAdapter;
import org.briarproject.api.privategroup.invitation.GroupInvitationItem;
class InvitationGroupAdapter extends
InvitationAdapter<GroupInvitationItem, GroupInvitationViewHolder> {
InvitationGroupAdapter(Context ctx,
InvitationClickListener<GroupInvitationItem> listener) {
super(ctx, GroupInvitationItem.class, listener);
}
@Override
public GroupInvitationViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
return new GroupInvitationViewHolder(getView(parent));
}
@Override
public boolean areContentsTheSame(GroupInvitationItem item1,
GroupInvitationItem item2) {
return item1.isSubscribed() == item2.isSubscribed();
}
}

View File

@@ -0,0 +1,47 @@
package org.briarproject.android.privategroup.invitation;
import android.content.Context;
import org.briarproject.R;
import org.briarproject.android.ActivityComponent;
import org.briarproject.android.sharing.InvitationAdapter;
import org.briarproject.android.sharing.InvitationsActivity;
import org.briarproject.api.privategroup.invitation.GroupInvitationItem;
import javax.inject.Inject;
import static org.briarproject.android.sharing.InvitationAdapter.InvitationClickListener;
public class InvitationsGroupActivity
extends InvitationsActivity<GroupInvitationItem> {
@Inject
protected InvitationsGroupController controller;
@Override
public void injectActivity(ActivityComponent component) {
component.inject(this);
}
@Override
protected InvitationsGroupController getController() {
return controller;
}
@Override
protected InvitationAdapter<GroupInvitationItem, ?> getAdapter(Context ctx,
InvitationClickListener listener) {
return new InvitationGroupAdapter(ctx, listener);
}
@Override
protected int getAcceptRes() {
return R.string.groups_invitations_joined;
}
@Override
protected int getDeclineRes() {
return R.string.groups_invitations_declined;
}
}

View File

@@ -0,0 +1,8 @@
package org.briarproject.android.privategroup.invitation;
import org.briarproject.android.sharing.InvitationsController;
import org.briarproject.api.privategroup.invitation.GroupInvitationItem;
public interface InvitationsGroupController
extends InvitationsController<GroupInvitationItem> {
}

View File

@@ -0,0 +1,83 @@
package org.briarproject.android.privategroup.invitation;
import org.briarproject.android.controller.handler.ResultExceptionHandler;
import org.briarproject.android.sharing.InvitationsControllerImpl;
import org.briarproject.api.contact.Contact;
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.GroupInvitationReceivedEvent;
import org.briarproject.api.lifecycle.LifecycleManager;
import org.briarproject.api.privategroup.PrivateGroup;
import org.briarproject.api.privategroup.PrivateGroupManager;
import org.briarproject.api.privategroup.invitation.GroupInvitationItem;
import org.briarproject.api.privategroup.invitation.GroupInvitationManager;
import org.briarproject.api.sync.ClientId;
import java.util.Collection;
import java.util.concurrent.Executor;
import javax.inject.Inject;
import static java.util.logging.Level.WARNING;
public class InvitationsGroupControllerImpl
extends InvitationsControllerImpl<GroupInvitationItem>
implements InvitationsGroupController {
private final PrivateGroupManager privateGroupManager;
private final GroupInvitationManager groupInvitationManager;
@Inject
InvitationsGroupControllerImpl(@DatabaseExecutor Executor dbExecutor,
LifecycleManager lifecycleManager, EventBus eventBus,
PrivateGroupManager privateGroupManager,
GroupInvitationManager groupInvitationManager) {
super(dbExecutor, lifecycleManager, eventBus);
this.privateGroupManager = privateGroupManager;
this.groupInvitationManager = groupInvitationManager;
}
@Override
public void eventOccurred(Event e) {
super.eventOccurred(e);
if (e instanceof GroupInvitationReceivedEvent) {
LOG.info("Group invitation received, reloading");
listener.loadInvitations(false);
}
}
@Override
protected ClientId getClientId() {
return privateGroupManager.getClientId();
}
@Override
protected Collection<GroupInvitationItem> getInvitations()
throws DbException {
return groupInvitationManager.getInvitations();
}
@Override
public void respondToInvitation(final GroupInvitationItem item,
final boolean accept,
final ResultExceptionHandler<Void, DbException> handler) {
runOnDbThread(new Runnable() {
@Override
public void run() {
try {
PrivateGroup g = (PrivateGroup) item.getShareable();
Contact c = item.getCreator();
groupInvitationManager.respondToInvitation(g, c, accept);
} catch (DbException e) {
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
handler.onException(e);
}
}
});
}
}

View File

@@ -30,6 +30,9 @@ public interface GroupListController extends DbController {
void removeGroup(GroupId g,
ResultExceptionHandler<Void, DbException> result);
void loadAvailableGroups(
ResultExceptionHandler<Integer, DbException> result);
interface GroupListListener extends DestroyableContext {
@UiThread

View File

@@ -20,6 +20,7 @@ import org.briarproject.api.lifecycle.LifecycleManager;
import org.briarproject.api.privategroup.GroupMessageHeader;
import org.briarproject.api.privategroup.PrivateGroup;
import org.briarproject.api.privategroup.PrivateGroupManager;
import org.briarproject.api.privategroup.invitation.GroupInvitationManager;
import org.briarproject.api.sync.ClientId;
import org.briarproject.api.sync.GroupId;
@@ -41,6 +42,7 @@ public class GroupListControllerImpl extends DbControllerImpl
Logger.getLogger(GroupListControllerImpl.class.getName());
private final PrivateGroupManager groupManager;
private final GroupInvitationManager groupInvitationManager;
private final EventBus eventBus;
private final AndroidNotificationManager notificationManager;
private final IdentityManager identityManager;
@@ -50,10 +52,12 @@ public class GroupListControllerImpl extends DbControllerImpl
@Inject
GroupListControllerImpl(@DatabaseExecutor Executor dbExecutor,
LifecycleManager lifecycleManager, PrivateGroupManager groupManager,
EventBus eventBus, AndroidNotificationManager notificationManager,
GroupInvitationManager groupInvitationManager, EventBus eventBus,
AndroidNotificationManager notificationManager,
IdentityManager identityManager) {
super(dbExecutor, lifecycleManager);
this.groupManager = groupManager;
this.groupInvitationManager = groupInvitationManager;
this.eventBus = eventBus;
this.notificationManager = notificationManager;
this.identityManager = identityManager;
@@ -187,4 +191,22 @@ public class GroupListControllerImpl extends DbControllerImpl
});
}
@Override
public void loadAvailableGroups(
final ResultExceptionHandler<Integer, DbException> handler) {
runOnDbThread(new Runnable() {
@Override
public void run() {
try {
handler.onResult(
groupInvitationManager.getInvitations().size());
} catch (DbException e) {
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
handler.onException(e);
}
}
});
}
}

View File

@@ -4,13 +4,16 @@ import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.annotation.UiThread;
import android.support.design.widget.Snackbar;
import android.support.v4.app.ActivityOptionsCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.LinearLayoutManager;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import org.briarproject.R;
@@ -18,6 +21,7 @@ import org.briarproject.android.ActivityComponent;
import org.briarproject.android.controller.handler.UiResultExceptionHandler;
import org.briarproject.android.fragment.BaseFragment;
import org.briarproject.android.privategroup.creation.CreateGroupActivity;
import org.briarproject.android.privategroup.invitation.InvitationsGroupActivity;
import org.briarproject.android.privategroup.list.GroupListController.GroupListListener;
import org.briarproject.android.privategroup.list.GroupViewHolder.OnGroupRemoveClickListener;
import org.briarproject.android.view.BriarRecyclerView;
@@ -30,10 +34,11 @@ import java.util.logging.Logger;
import javax.inject.Inject;
import static android.support.design.widget.Snackbar.LENGTH_INDEFINITE;
import static android.support.v4.app.ActivityOptionsCompat.makeCustomAnimation;
public class GroupListFragment extends BaseFragment implements
GroupListListener, OnGroupRemoveClickListener {
GroupListListener, OnGroupRemoveClickListener, OnClickListener {
public final static String TAG = GroupListFragment.class.getName();
private static final Logger LOG = Logger.getLogger(TAG);
@@ -47,6 +52,7 @@ public class GroupListFragment extends BaseFragment implements
private BriarRecyclerView list;
private GroupListAdapter adapter;
private Snackbar snackbar;
@Nullable
@Override
@@ -61,6 +67,12 @@ public class GroupListFragment extends BaseFragment implements
list.setLayoutManager(new LinearLayoutManager(getContext()));
list.setAdapter(adapter);
snackbar = Snackbar.make(list, "", LENGTH_INDEFINITE);
snackbar.getView().setBackgroundResource(R.color.briar_primary);
snackbar.setAction(R.string.show, this);
snackbar.setActionTextColor(ContextCompat
.getColor(getContext(), R.color.briar_button_positive));
return v;
}
@@ -76,6 +88,7 @@ public class GroupListFragment extends BaseFragment implements
controller.onStart();
list.startPeriodicUpdate();
loadGroups();
loadAvailableGroups();
}
@Override
@@ -180,4 +193,40 @@ public class GroupListFragment extends BaseFragment implements
});
}
private void loadAvailableGroups() {
controller.loadAvailableGroups(
new UiResultExceptionHandler<Integer, DbException>(this) {
@Override
public void onResultUi(Integer num) {
if (num == 0) {
snackbar.dismiss();
} else {
snackbar.setText(getResources().getQuantityString(
R.plurals.groups_invitations_open, num,
num));
if (!snackbar.isShownOrQueued()) snackbar.show();
}
}
@Override
public void onExceptionUi(DbException exception) {
// TODO handle this error
finish();
}
});
}
/**
* This method is handling the available groups snackbar action
*/
@Override
public void onClick(View v) {
Intent i = new Intent(getContext(), InvitationsGroupActivity.class);
ActivityOptionsCompat options =
makeCustomAnimation(getActivity(),
android.R.anim.slide_in_left,
android.R.anim.slide_out_right);
startActivity(i, options.toBundle());
}
}