Controllerize invitation activities

This commit is contained in:
Torsten Grote
2016-10-14 17:29:46 -03:00
parent 02a39f5694
commit a92f7e1c9f
16 changed files with 568 additions and 366 deletions

View File

@@ -27,6 +27,10 @@ import org.briarproject.android.privategroup.creation.CreateGroupController;
import org.briarproject.android.privategroup.creation.CreateGroupControllerImpl;
import org.briarproject.android.privategroup.list.GroupListController;
import org.briarproject.android.privategroup.list.GroupListControllerImpl;
import org.briarproject.android.sharing.InvitationsBlogController;
import org.briarproject.android.sharing.InvitationsBlogControllerImpl;
import org.briarproject.android.sharing.InvitationsForumController;
import org.briarproject.android.sharing.InvitationsForumControllerImpl;
import dagger.Module;
import dagger.Provides;
@@ -125,6 +129,22 @@ public class ActivityModule {
return forumController;
}
@ActivityScope
@Provides
protected InvitationsForumController provideInvitationsForumController(
InvitationsForumControllerImpl invitationsForumController) {
activity.addLifecycleController(invitationsForumController);
return invitationsForumController;
}
@ActivityScope
@Provides
protected InvitationsBlogController provideInvitationsBlogController(
InvitationsBlogControllerImpl invitationsBlogController) {
activity.addLifecycleController(invitationsBlogController);
return invitationsBlogController;
}
@ActivityScope
@Provides
BlogController provideBlogController(BlogControllerImpl blogController) {

View File

@@ -1,40 +0,0 @@
package org.briarproject.android.sharing;
import android.content.Context;
import org.briarproject.R;
import org.briarproject.api.blogs.Blog;
import org.briarproject.api.sharing.InvitationItem;
class BlogInvitationAdapter extends InvitationAdapter {
BlogInvitationAdapter(Context ctx, AvailableForumClickListener listener) {
super(ctx, listener);
}
@Override
public void onBindViewHolder(InvitationsViewHolder ui, int position) {
super.onBindViewHolder(ui, position);
InvitationItem item = getItemAt(position);
if (item == null) return;
Blog blog = (Blog) item.getShareable();
ui.avatar.setAuthorAvatar(blog.getAuthor());
ui.name.setText(ctx.getString(R.string.blogs_personal_blog,
blog.getAuthor().getName()));
if (item.isSubscribed()) {
ui.subscribed.setText(ctx.getString(R.string.blogs_sharing_exists));
}
}
@Override
public int compare(InvitationItem o1, InvitationItem o2) {
return String.CASE_INSENSITIVE_ORDER
.compare(((Blog) o1.getShareable()).getAuthor().getName(),
((Blog) o2.getShareable()).getAuthor().getName());
}
}

View File

@@ -1,35 +0,0 @@
package org.briarproject.android.sharing;
import android.content.Context;
import org.briarproject.api.forum.Forum;
import org.briarproject.api.sharing.InvitationItem;
class ForumInvitationAdapter extends InvitationAdapter {
ForumInvitationAdapter(Context ctx, AvailableForumClickListener listener) {
super(ctx, listener);
}
@Override
public void onBindViewHolder(InvitationsViewHolder ui, int position) {
super.onBindViewHolder(ui, position);
InvitationItem item = getItemAt(position);
if (item == null) return;
Forum forum = (Forum) item.getShareable();
ui.avatar.setText(forum.getName().substring(0, 1));
ui.avatar.setBackgroundBytes(item.getShareable().getId().getBytes());
ui.name.setText(forum.getName());
}
@Override
public int compare(InvitationItem o1, InvitationItem o2) {
return String.CASE_INSENSITIVE_ORDER
.compare(((Forum) o1.getShareable()).getName(),
((Forum) o2.getShareable()).getName());
}
}

View File

@@ -1,111 +1,51 @@
package org.briarproject.android.sharing;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import org.briarproject.R;
import org.briarproject.android.util.BriarAdapter;
import org.briarproject.android.view.TextAvatarView;
import org.briarproject.api.contact.Contact;
import org.briarproject.api.sharing.InvitationItem;
import org.briarproject.util.StringUtils;
import java.util.ArrayList;
import java.util.Collection;
public abstract class InvitationAdapter<I extends InvitationItem, VH extends InvitationViewHolder<I>>
extends BriarAdapter<I, VH> {
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
private final InvitationClickListener<I> listener;
abstract class InvitationAdapter extends
BriarAdapter<InvitationItem, InvitationAdapter.InvitationsViewHolder> {
private final AvailableForumClickListener listener;
InvitationAdapter(Context ctx, AvailableForumClickListener listener) {
super(ctx, InvitationItem.class);
public InvitationAdapter(Context ctx, Class<I> c,
InvitationClickListener<I> listener) {
super(ctx, c);
this.listener = listener;
}
@Override
public InvitationsViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View v = LayoutInflater.from(ctx)
.inflate(R.layout.list_item_invitations, parent, false);
return new InvitationsViewHolder(v);
protected View getView(ViewGroup parent) {
return LayoutInflater.from(ctx)
.inflate(R.layout.list_item_invitations, parent, false);
}
@Override
public void onBindViewHolder(InvitationsViewHolder ui, int position) {
final InvitationItem item = getItemAt(position);
public void onBindViewHolder(VH ui, int position) {
final I item = getItemAt(position);
if (item == null) return;
Collection<String> names = new ArrayList<>();
for (Contact c : item.getNewSharers())
names.add(c.getAuthor().getName());
ui.sharedBy.setText(ctx.getString(R.string.shared_by_format,
StringUtils.join(names, ", ")));
if (item.isSubscribed()) {
ui.subscribed.setVisibility(VISIBLE);
} else {
ui.subscribed.setVisibility(GONE);
}
ui.accept.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
listener.onItemClick(item, true);
}
});
ui.decline.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
listener.onItemClick(item, false);
}
});
ui.onBind(item, listener);
}
@Override
public boolean areContentsTheSame(InvitationItem oldItem,
InvitationItem newItem) {
return oldItem.isSubscribed() == newItem.isSubscribed() &&
oldItem.getNewSharers().equals(newItem.getNewSharers());
}
@Override
public boolean areItemsTheSame(InvitationItem oldItem,
InvitationItem newItem) {
public boolean areItemsTheSame(I oldItem, I newItem) {
return oldItem.getShareable().equals(newItem.getShareable());
}
static class InvitationsViewHolder extends RecyclerView.ViewHolder {
final TextAvatarView avatar;
final TextView name;
private final TextView sharedBy;
final TextView subscribed;
private final Button accept;
private final Button decline;
private InvitationsViewHolder(View v) {
super(v);
avatar = (TextAvatarView) v.findViewById(R.id.avatarView);
name = (TextView) v.findViewById(R.id.forumNameView);
sharedBy = (TextView) v.findViewById(R.id.sharedByView);
subscribed = (TextView) v.findViewById(R.id.forumSubscribedView);
accept = (Button) v.findViewById(R.id.acceptButton);
decline = (Button) v.findViewById(R.id.declineButton);
}
@Override
public int compare(I o1, I o2) {
return String.CASE_INSENSITIVE_ORDER
.compare((o1.getShareable()).getName(),
(o2.getShareable()).getName());
}
interface AvailableForumClickListener {
void onItemClick(InvitationItem item, boolean accept);
public interface InvitationClickListener<I> {
void onItemClick(I item, boolean accept);
}
}

View File

@@ -0,0 +1,69 @@
package org.briarproject.android.sharing;
import android.support.annotation.CallSuper;
import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import org.briarproject.R;
import org.briarproject.android.sharing.InvitationAdapter.InvitationClickListener;
import org.briarproject.android.view.TextAvatarView;
import org.briarproject.api.sharing.InvitationItem;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
public class InvitationViewHolder<I extends InvitationItem>
extends RecyclerView.ViewHolder {
private final TextAvatarView avatar;
private final TextView name;
protected final TextView sharedBy;
private final TextView subscribed;
private final Button accept;
private final Button decline;
public InvitationViewHolder(View v) {
super(v);
avatar = (TextAvatarView) v.findViewById(R.id.avatarView);
name = (TextView) v.findViewById(R.id.forumNameView);
sharedBy = (TextView) v.findViewById(R.id.sharedByView);
subscribed = (TextView) v.findViewById(R.id.forumSubscribedView);
accept = (Button) v.findViewById(R.id.acceptButton);
decline = (Button) v.findViewById(R.id.declineButton);
}
@CallSuper
public void onBind(@Nullable final I item,
final InvitationClickListener<I> listener) {
if (item == null) return;
avatar.setText(item.getShareable().getName().substring(0, 1));
avatar.setBackgroundBytes(item.getShareable().getId().getBytes());
name.setText(item.getShareable().getName());
if (item.isSubscribed()) {
subscribed.setVisibility(VISIBLE);
} else {
subscribed.setVisibility(GONE);
}
accept.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
listener.onItemClick(item, true);
}
});
decline.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
listener.onItemClick(item, false);
}
});
}
}

View File

@@ -2,39 +2,34 @@ package org.briarproject.android.sharing;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.CallSuper;
import android.support.annotation.StringRes;
import android.support.v7.widget.LinearLayoutManager;
import android.widget.Toast;
import org.briarproject.R;
import org.briarproject.android.BriarActivity;
import org.briarproject.android.controller.handler.UiResultExceptionHandler;
import org.briarproject.android.sharing.InvitationsController.InvitationListener;
import org.briarproject.android.view.BriarRecyclerView;
import org.briarproject.api.event.ContactRemovedEvent;
import org.briarproject.api.event.Event;
import org.briarproject.api.event.EventBus;
import org.briarproject.api.event.EventListener;
import org.briarproject.api.db.DbException;
import org.briarproject.api.sharing.InvitationItem;
import java.util.Collection;
import java.util.logging.Logger;
import javax.inject.Inject;
import static android.widget.Toast.LENGTH_SHORT;
import static org.briarproject.android.sharing.InvitationAdapter.AvailableForumClickListener;
import static org.briarproject.android.sharing.InvitationAdapter.InvitationClickListener;
abstract class InvitationsActivity extends BriarActivity
implements EventListener, AvailableForumClickListener {
public abstract class InvitationsActivity<I extends InvitationItem>
extends BriarActivity
implements InvitationListener, InvitationClickListener<I> {
protected static final Logger LOG =
Logger.getLogger(InvitationsActivity.class.getName());
protected InvitationAdapter adapter;
private InvitationAdapter<I, ?> adapter;
private BriarRecyclerView list;
@Inject
EventBus eventBus;
@Override
public void onCreate(Bundle state) {
super.onCreate(state);
@@ -42,7 +37,6 @@ abstract class InvitationsActivity extends BriarActivity
setContentView(R.layout.list);
adapter = getAdapter(this, this);
list = (BriarRecyclerView) findViewById(R.id.list);
if (list != null) {
list.setLayoutManager(new LinearLayoutManager(this));
@@ -50,32 +44,24 @@ abstract class InvitationsActivity extends BriarActivity
}
}
abstract protected InvitationAdapter<I, ?> getAdapter(Context ctx,
InvitationClickListener listener);
@Override
public void onStart() {
super.onStart();
eventBus.addListener(this);
loadInvitations(false);
}
@Override
public void onStop() {
super.onStop();
eventBus.removeListener(this);
adapter.clear();
list.showProgressBar();
}
@Override
@CallSuper
public void eventOccurred(Event e) {
if (e instanceof ContactRemovedEvent) {
LOG.info("Contact removed, reloading...");
loadInvitations(true);
}
}
@Override
public void onItemClick(InvitationItem item, boolean accept) {
public void onItemClick(I item, boolean accept) {
respondToInvitation(item, accept);
// show toast
@@ -91,26 +77,58 @@ abstract class InvitationsActivity extends BriarActivity
}
}
abstract protected InvitationAdapter getAdapter(Context ctx,
AvailableForumClickListener listener);
@Override
public void loadInvitations(final boolean clear) {
final int revision = adapter.getRevision();
getController().loadInvitations(clear,
new UiResultExceptionHandler<Collection<I>, DbException>(
this) {
@Override
public void onResultUi(Collection<I> items) {
displayInvitations(revision, items, clear);
}
abstract protected void loadInvitations(boolean clear);
@Override
public void onExceptionUi(DbException exception) {
// TODO proper error handling
finish();
}
});
}
abstract protected void respondToInvitation(final InvitationItem item,
final boolean accept);
abstract protected InvitationsController<I> getController();
protected void respondToInvitation(final I item,
final boolean accept) {
getController().respondToInvitation(item, accept,
new UiResultExceptionHandler<Void, DbException>(this) {
@Override
public void onResultUi(Void result) {
}
@Override
public void onExceptionUi(DbException exception) {
// TODO proper error handling
finish();
}
});
}
@StringRes
abstract protected int getAcceptRes();
@StringRes
abstract protected int getDeclineRes();
protected void displayInvitations(final int revision,
final Collection<InvitationItem> invitations, final boolean clear) {
final Collection<I> invitations, final boolean clear) {
runOnUiThreadUnlessDestroyed(new Runnable() {
@Override
public void run() {
if (invitations.isEmpty()) {
LOG.info("No more invitations available, finishing");
finish();
supportFinishAfterTransition();
} else if (revision == adapter.getRevision()) {
adapter.incrementRevision();
if (clear) adapter.setItems(invitations);

View File

@@ -4,34 +4,17 @@ import android.content.Context;
import org.briarproject.R;
import org.briarproject.android.ActivityComponent;
import org.briarproject.api.blogs.Blog;
import org.briarproject.api.blogs.BlogManager;
import org.briarproject.api.blogs.BlogSharingManager;
import org.briarproject.api.contact.Contact;
import org.briarproject.api.db.DbException;
import org.briarproject.api.event.BlogInvitationReceivedEvent;
import org.briarproject.api.event.Event;
import org.briarproject.api.event.GroupAddedEvent;
import org.briarproject.api.event.GroupRemovedEvent;
import org.briarproject.api.sharing.InvitationItem;
import org.briarproject.api.sync.ClientId;
import java.util.ArrayList;
import java.util.Collection;
import org.briarproject.api.sharing.SharingInvitationItem;
import javax.inject.Inject;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static org.briarproject.android.sharing.InvitationAdapter.AvailableForumClickListener;
import static org.briarproject.android.sharing.InvitationAdapter.InvitationClickListener;
public class InvitationsBlogActivity extends InvitationsActivity {
public class InvitationsBlogActivity
extends InvitationsActivity<SharingInvitationItem> {
// Fields that are accessed from background threads must be volatile
@Inject
volatile BlogManager blogManager;
@Inject
volatile BlogSharingManager blogSharingManager;
InvitationsBlogController controller;
@Override
public void injectActivity(ActivityComponent component) {
@@ -39,75 +22,14 @@ public class InvitationsBlogActivity extends InvitationsActivity {
}
@Override
public void eventOccurred(Event e) {
super.eventOccurred(e);
if (e instanceof GroupAddedEvent) {
GroupAddedEvent g = (GroupAddedEvent) e;
ClientId cId = g.getGroup().getClientId();
if (cId.equals(blogManager.getClientId())) {
LOG.info("Blog added, reloading");
loadInvitations(false);
}
} else if (e instanceof GroupRemovedEvent) {
GroupRemovedEvent g = (GroupRemovedEvent) e;
ClientId cId = g.getGroup().getClientId();
if (cId.equals(blogManager.getClientId())) {
LOG.info("Blog removed, reloading");
loadInvitations(false);
}
} else if (e instanceof BlogInvitationReceivedEvent) {
LOG.info("Blog invitation received, reloading");
loadInvitations(false);
}
protected InvitationsController<SharingInvitationItem> getController() {
return controller;
}
@Override
protected InvitationAdapter getAdapter(Context ctx,
AvailableForumClickListener listener) {
return new BlogInvitationAdapter(ctx, listener);
}
@Override
protected void loadInvitations(final boolean clear) {
final int revision = adapter.getRevision();
runOnDbThread(new Runnable() {
@Override
public void run() {
try {
Collection<InvitationItem> invitations = new ArrayList<>();
long now = System.currentTimeMillis();
invitations.addAll(blogSharingManager.getInvitations());
long duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO))
LOG.info("Load took " + duration + " ms");
displayInvitations(revision, invitations, clear);
} catch (DbException e) {
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
}
}
});
}
@Override
protected void respondToInvitation(final InvitationItem item,
final boolean accept) {
runOnDbThread(new Runnable() {
@Override
public void run() {
try {
Blog b = (Blog) item.getShareable();
for (Contact c : item.getNewSharers()) {
// TODO: What happens if a contact has been removed?
blogSharingManager.respondToInvitation(b, c, accept);
}
} catch (DbException e) {
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
}
}
});
protected InvitationAdapter<SharingInvitationItem, ?> getAdapter(
Context ctx, InvitationClickListener listener) {
return new SharingInvitationAdapter(ctx, listener);
}
@Override
@@ -119,4 +41,5 @@ public class InvitationsBlogActivity extends InvitationsActivity {
protected int getDeclineRes() {
return R.string.blogs_sharing_declined_toast;
}
}

View File

@@ -0,0 +1,7 @@
package org.briarproject.android.sharing;
import org.briarproject.api.sharing.SharingInvitationItem;
public interface InvitationsBlogController
extends InvitationsController<SharingInvitationItem> {
}

View File

@@ -0,0 +1,82 @@
package org.briarproject.android.sharing;
import org.briarproject.android.controller.handler.ResultExceptionHandler;
import org.briarproject.api.blogs.Blog;
import org.briarproject.api.blogs.BlogManager;
import org.briarproject.api.blogs.BlogSharingManager;
import org.briarproject.api.contact.Contact;
import org.briarproject.api.db.DatabaseExecutor;
import org.briarproject.api.db.DbException;
import org.briarproject.api.event.BlogInvitationReceivedEvent;
import org.briarproject.api.event.Event;
import org.briarproject.api.event.EventBus;
import org.briarproject.api.lifecycle.LifecycleManager;
import org.briarproject.api.sharing.SharingInvitationItem;
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 InvitationsBlogControllerImpl
extends InvitationsControllerImpl<SharingInvitationItem>
implements InvitationsBlogController {
private final BlogManager blogManager;
private final BlogSharingManager blogSharingManager;
@Inject
InvitationsBlogControllerImpl(@DatabaseExecutor Executor dbExecutor,
LifecycleManager lifecycleManager, EventBus eventBus,
BlogManager blogManager, BlogSharingManager blogSharingManager) {
super(dbExecutor, lifecycleManager, eventBus);
this.blogManager = blogManager;
this.blogSharingManager = blogSharingManager;
}
@Override
public void eventOccurred(Event e) {
super.eventOccurred(e);
if (e instanceof BlogInvitationReceivedEvent) {
LOG.info("Blog invitation received, reloading");
listener.loadInvitations(false);
}
}
@Override
protected ClientId getClientId() {
return blogManager.getClientId();
}
@Override
protected Collection<SharingInvitationItem> getInvitations() throws DbException {
return blogSharingManager.getInvitations();
}
@Override
public void respondToInvitation(final SharingInvitationItem item,
final boolean accept,
final ResultExceptionHandler<Void, DbException> handler) {
runOnDbThread(new Runnable() {
@Override
public void run() {
try {
Blog f = (Blog) item.getShareable();
for (Contact c : item.getNewSharers()) {
// TODO: What happens if a contact has been removed?
blogSharingManager.respondToInvitation(f, c, accept);
}
} catch (DbException e) {
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
handler.onException(e);
}
}
});
}
}

View File

@@ -0,0 +1,25 @@
package org.briarproject.android.sharing;
import org.briarproject.android.controller.ActivityLifecycleController;
import org.briarproject.android.controller.handler.ResultExceptionHandler;
import org.briarproject.api.db.DbException;
import org.briarproject.api.sharing.InvitationItem;
import java.util.Collection;
public interface InvitationsController<I extends InvitationItem>
extends ActivityLifecycleController {
void loadInvitations(boolean clear,
ResultExceptionHandler<Collection<I>, DbException> handler);
void respondToInvitation(I item, boolean accept,
ResultExceptionHandler<Void, DbException> handler);
interface InvitationListener {
void loadInvitations(boolean clear);
}
}

View File

@@ -0,0 +1,116 @@
package org.briarproject.android.sharing;
import android.app.Activity;
import android.support.annotation.CallSuper;
import org.briarproject.android.controller.DbControllerImpl;
import org.briarproject.android.controller.handler.ResultExceptionHandler;
import org.briarproject.api.db.DatabaseExecutor;
import org.briarproject.api.db.DbException;
import org.briarproject.api.event.ContactRemovedEvent;
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.GroupRemovedEvent;
import org.briarproject.api.lifecycle.LifecycleManager;
import org.briarproject.api.sharing.InvitationItem;
import org.briarproject.api.sync.ClientId;
import java.util.ArrayList;
import java.util.Collection;
import java.util.concurrent.Executor;
import java.util.logging.Logger;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
public abstract class InvitationsControllerImpl<I extends InvitationItem>
extends DbControllerImpl
implements InvitationsController<I>, EventListener {
protected static final Logger LOG =
Logger.getLogger(InvitationsControllerImpl.class.getName());
private final EventBus eventBus;
protected InvitationListener listener;
public InvitationsControllerImpl(@DatabaseExecutor Executor dbExecutor,
LifecycleManager lifecycleManager, EventBus eventBus) {
super(dbExecutor, lifecycleManager);
this.eventBus = eventBus;
}
@Override
public void onActivityCreate(Activity activity) {
listener = (InvitationListener) activity;
}
@Override
public void onActivityStart() {
eventBus.addListener(this);
}
@Override
public void onActivityStop() {
eventBus.removeListener(this);
}
@Override
public void onActivityDestroy() {
}
@CallSuper
@Override
public void eventOccurred(Event e) {
if (e instanceof ContactRemovedEvent) {
LOG.info("Contact removed, reloading...");
listener.loadInvitations(true);
} else if (e instanceof GroupAddedEvent) {
GroupAddedEvent g = (GroupAddedEvent) e;
ClientId cId = g.getGroup().getClientId();
if (cId.equals(getClientId())) {
LOG.info("Group added, reloading");
listener.loadInvitations(false);
}
} else if (e instanceof GroupRemovedEvent) {
GroupRemovedEvent g = (GroupRemovedEvent) e;
ClientId cId = g.getGroup().getClientId();
if (cId.equals(getClientId())) {
LOG.info("Group removed, reloading");
listener.loadInvitations(true);
}
}
}
protected abstract ClientId getClientId();
@Override
public void loadInvitations(final boolean clear,
final ResultExceptionHandler<Collection<I>, DbException> handler) {
runOnDbThread(new Runnable() {
@Override
public void run() {
Collection<I> invitations = new ArrayList<>();
try {
long now = System.currentTimeMillis();
invitations.addAll(getInvitations());
long duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO))
LOG.info(
"Loading invitations took " + duration + " ms");
handler.onResult(invitations);
} catch (DbException e) {
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
handler.onException(e);
}
}
});
}
@DatabaseExecutor
protected abstract Collection<I> getInvitations() throws DbException;
}

View File

@@ -4,34 +4,17 @@ import android.content.Context;
import org.briarproject.R;
import org.briarproject.android.ActivityComponent;
import org.briarproject.api.contact.Contact;
import org.briarproject.api.db.DbException;
import org.briarproject.api.event.Event;
import org.briarproject.api.event.ForumInvitationReceivedEvent;
import org.briarproject.api.event.GroupAddedEvent;
import org.briarproject.api.event.GroupRemovedEvent;
import org.briarproject.api.forum.Forum;
import org.briarproject.api.forum.ForumManager;
import org.briarproject.api.forum.ForumSharingManager;
import org.briarproject.api.sharing.InvitationItem;
import org.briarproject.api.sync.ClientId;
import java.util.ArrayList;
import java.util.Collection;
import org.briarproject.api.sharing.SharingInvitationItem;
import javax.inject.Inject;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static org.briarproject.android.sharing.InvitationAdapter.AvailableForumClickListener;
import static org.briarproject.android.sharing.InvitationAdapter.InvitationClickListener;
public class InvitationsForumActivity extends InvitationsActivity {
public class InvitationsForumActivity
extends InvitationsActivity<SharingInvitationItem> {
// Fields that are accessed from background threads must be volatile
@Inject
volatile ForumManager forumManager;
@Inject
volatile ForumSharingManager forumSharingManager;
InvitationsForumController controller;
@Override
public void injectActivity(ActivityComponent component) {
@@ -39,75 +22,14 @@ public class InvitationsForumActivity extends InvitationsActivity {
}
@Override
public void eventOccurred(Event e) {
super.eventOccurred(e);
if (e instanceof GroupAddedEvent) {
GroupAddedEvent g = (GroupAddedEvent) e;
ClientId cId = g.getGroup().getClientId();
if (cId.equals(forumManager.getClientId())) {
LOG.info("Forum added, reloading");
loadInvitations(false);
}
} else if (e instanceof GroupRemovedEvent) {
GroupRemovedEvent g = (GroupRemovedEvent) e;
ClientId cId = g.getGroup().getClientId();
if (cId.equals(forumManager.getClientId())) {
LOG.info("Forum removed, reloading");
loadInvitations(false);
}
} else if (e instanceof ForumInvitationReceivedEvent) {
LOG.info("Forum invitation received, reloading");
loadInvitations(false);
}
protected InvitationsController<SharingInvitationItem> getController() {
return controller;
}
@Override
protected InvitationAdapter getAdapter(Context ctx,
AvailableForumClickListener listener) {
return new ForumInvitationAdapter(ctx, listener);
}
@Override
protected void loadInvitations(final boolean clear) {
final int revision = adapter.getRevision();
runOnDbThread(new Runnable() {
@Override
public void run() {
try {
Collection<InvitationItem> invitations = new ArrayList<>();
long now = System.currentTimeMillis();
invitations.addAll(forumSharingManager.getInvitations());
long duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO))
LOG.info("Load took " + duration + " ms");
displayInvitations(revision, invitations, clear);
} catch (DbException e) {
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
}
}
});
}
@Override
protected void respondToInvitation(final InvitationItem item,
final boolean accept) {
runOnDbThread(new Runnable() {
@Override
public void run() {
try {
Forum f = (Forum) item.getShareable();
for (Contact c : item.getNewSharers()) {
// TODO: What happens if a contact has been removed?
forumSharingManager.respondToInvitation(f, c, accept);
}
} catch (DbException e) {
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
}
}
});
protected InvitationAdapter<SharingInvitationItem, ?> getAdapter(
Context ctx, InvitationClickListener listener) {
return new SharingInvitationAdapter(ctx, listener);
}
@Override
@@ -119,4 +41,5 @@ public class InvitationsForumActivity extends InvitationsActivity {
protected int getDeclineRes() {
return R.string.forum_declined_toast;
}
}

View File

@@ -0,0 +1,7 @@
package org.briarproject.android.sharing;
import org.briarproject.api.sharing.SharingInvitationItem;
public interface InvitationsForumController
extends InvitationsController<SharingInvitationItem> {
}

View File

@@ -0,0 +1,83 @@
package org.briarproject.android.sharing;
import org.briarproject.android.controller.handler.ResultExceptionHandler;
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.ForumInvitationReceivedEvent;
import org.briarproject.api.forum.Forum;
import org.briarproject.api.forum.ForumManager;
import org.briarproject.api.forum.ForumSharingManager;
import org.briarproject.api.lifecycle.LifecycleManager;
import org.briarproject.api.sharing.SharingInvitationItem;
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 InvitationsForumControllerImpl
extends InvitationsControllerImpl<SharingInvitationItem>
implements InvitationsForumController {
private final ForumManager forumManager;
private final ForumSharingManager forumSharingManager;
@Inject
InvitationsForumControllerImpl(@DatabaseExecutor Executor dbExecutor,
LifecycleManager lifecycleManager, EventBus eventBus,
ForumManager forumManager,
ForumSharingManager forumSharingManager) {
super(dbExecutor, lifecycleManager, eventBus);
this.forumManager = forumManager;
this.forumSharingManager = forumSharingManager;
}
@Override
public void eventOccurred(Event e) {
super.eventOccurred(e);
if (e instanceof ForumInvitationReceivedEvent) {
LOG.info("Forum invitation received, reloading");
listener.loadInvitations(false);
}
}
@Override
protected ClientId getClientId() {
return forumManager.getClientId();
}
@Override
protected Collection<SharingInvitationItem> getInvitations() throws DbException {
return forumSharingManager.getInvitations();
}
@Override
public void respondToInvitation(final SharingInvitationItem item,
final boolean accept,
final ResultExceptionHandler<Void, DbException> handler) {
runOnDbThread(new Runnable() {
@Override
public void run() {
try {
Forum f = (Forum) item.getShareable();
for (Contact c : item.getNewSharers()) {
// TODO: What happens if a contact has been removed?
forumSharingManager.respondToInvitation(f, c, accept);
}
} catch (DbException e) {
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
handler.onException(e);
}
}
});
}
}

View File

@@ -0,0 +1,29 @@
package org.briarproject.android.sharing;
import android.content.Context;
import android.view.ViewGroup;
import org.briarproject.api.sharing.SharingInvitationItem;
class SharingInvitationAdapter extends
InvitationAdapter<SharingInvitationItem, SharingInvitationViewHolder> {
SharingInvitationAdapter(Context ctx, InvitationClickListener listener) {
super(ctx, SharingInvitationItem.class, listener);
}
@Override
public SharingInvitationViewHolder onCreateViewHolder(
ViewGroup parent,
int viewType) {
return new SharingInvitationViewHolder(getView(parent));
}
@Override
public boolean areContentsTheSame(SharingInvitationItem oldItem,
SharingInvitationItem newItem) {
return oldItem.isSubscribed() == newItem.isSubscribed() &&
oldItem.getNewSharers().equals(newItem.getNewSharers());
}
}

View File

@@ -0,0 +1,35 @@
package org.briarproject.android.sharing;
import android.support.annotation.Nullable;
import android.view.View;
import org.briarproject.R;
import org.briarproject.api.contact.Contact;
import org.briarproject.api.sharing.SharingInvitationItem;
import org.briarproject.util.StringUtils;
import java.util.ArrayList;
import java.util.Collection;
public class SharingInvitationViewHolder
extends InvitationViewHolder<SharingInvitationItem> {
public SharingInvitationViewHolder(View v) {
super(v);
}
@Override
public void onBind(@Nullable final SharingInvitationItem item,
final InvitationAdapter.InvitationClickListener<SharingInvitationItem> listener) {
super.onBind(item, listener);
if (item == null) return;
Collection<String> names = new ArrayList<>();
for (Contact c : item.getNewSharers())
names.add(c.getAuthor().getName());
sharedBy.setText(
sharedBy.getContext().getString(R.string.shared_by_format,
StringUtils.join(names, ", ")));
}
}