Use start/stop lifecycle callbacks rather than pause/resume.

Also fixed a couple of bugs.
This commit is contained in:
akwizgran
2016-10-12 16:55:00 +01:00
parent b3e5d1ff85
commit 50a70f7649
51 changed files with 563 additions and 538 deletions

View File

@@ -12,7 +12,6 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import static android.view.WindowManager.LayoutParams.FLAG_SECURE; import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
import static android.view.inputmethod.InputMethodManager.SHOW_FORCED;
import static android.view.inputmethod.InputMethodManager.SHOW_IMPLICIT; import static android.view.inputmethod.InputMethodManager.SHOW_IMPLICIT;
import static org.briarproject.android.TestingConstants.PREVENT_SCREENSHOTS; import static org.briarproject.android.TestingConstants.PREVENT_SCREENSHOTS;
@@ -62,18 +61,18 @@ public abstract class BaseActivity extends AppCompatActivity
} }
@Override @Override
protected void onResume() { protected void onStart() {
super.onResume(); super.onStart();
for (ActivityLifecycleController alc : lifecycleControllers) { for (ActivityLifecycleController alc : lifecycleControllers) {
alc.onActivityResume(); alc.onActivityStart();
} }
} }
@Override @Override
protected void onPause() { protected void onStop() {
super.onPause(); super.onStop();
for (ActivityLifecycleController alc : lifecycleControllers) { for (ActivityLifecycleController alc : lifecycleControllers) {
alc.onActivityPause(); alc.onActivityStop();
} }
} }

View File

@@ -34,10 +34,11 @@ public abstract class BriarActivity extends BaseActivity {
Logger.getLogger(BriarActivity.class.getName()); Logger.getLogger(BriarActivity.class.getName());
@Inject @Inject
protected BriarController briarController; BriarController briarController;
// TODO remove this when the deprecated method runOnDbThread is removed
@Deprecated
@Inject @Inject
protected DbController dbController; DbController dbController;
@Override @Override
protected void onActivityResult(int request, int result, Intent data) { protected void onActivityResult(int request, int result, Intent data) {
@@ -49,8 +50,8 @@ public abstract class BriarActivity extends BaseActivity {
} }
@Override @Override
public void onResume() { public void onStart() {
super.onResume(); super.onStart();
if (!briarController.hasEncryptionKey() && !isFinishing()) { if (!briarController.hasEncryptionKey() && !isFinishing()) {
Intent i = new Intent(this, PasswordActivity.class); Intent i = new Intent(this, PasswordActivity.class);
i.setFlags(FLAG_ACTIVITY_NO_ANIMATION | FLAG_ACTIVITY_SINGLE_TOP); i.setFlags(FLAG_ACTIVITY_NO_ANIMATION | FLAG_ACTIVITY_SINGLE_TOP);

View File

@@ -141,8 +141,8 @@ public class NavDrawerActivity extends BriarFragmentActivity implements
} }
@Override @Override
public void onResume() { public void onStart() {
super.onResume(); super.onStart();
updateTransports(); updateTransports();
} }

View File

@@ -12,8 +12,6 @@ import org.briarproject.api.blogs.BlogManager;
import org.briarproject.api.blogs.BlogPostHeader; import org.briarproject.api.blogs.BlogPostHeader;
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.BlogPostAddedEvent;
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.identity.IdentityManager; import org.briarproject.api.identity.IdentityManager;
@@ -47,7 +45,7 @@ abstract class BaseControllerImpl extends DbControllerImpl
private final Map<MessageId, BlogPostHeader> headerCache = private final Map<MessageId, BlogPostHeader> headerCache =
new ConcurrentHashMap<>(); new ConcurrentHashMap<>();
protected volatile OnBlogPostAddedListener listener; private volatile OnBlogPostAddedListener listener;
BaseControllerImpl(@DatabaseExecutor Executor dbExecutor, BaseControllerImpl(@DatabaseExecutor Executor dbExecutor,
LifecycleManager lifecycleManager, EventBus eventBus, LifecycleManager lifecycleManager, EventBus eventBus,
@@ -63,9 +61,7 @@ abstract class BaseControllerImpl extends DbControllerImpl
@Override @Override
@CallSuper @CallSuper
public void onStart() { public void onStart() {
if (listener == null) if (listener == null) throw new IllegalStateException();
throw new IllegalStateException(
"OnBlogPostAddedListener needs to be attached");
eventBus.addListener(this); eventBus.addListener(this);
} }
@@ -75,26 +71,30 @@ abstract class BaseControllerImpl extends DbControllerImpl
eventBus.removeListener(this); eventBus.removeListener(this);
} }
@Override
@CallSuper
public void eventOccurred(Event e) {
if (e instanceof BlogPostAddedEvent) {
final BlogPostAddedEvent b = (BlogPostAddedEvent) e;
LOG.info("New blog post added");
listener.runOnUiThreadUnlessDestroyed(new Runnable() {
@Override
public void run() {
listener.onBlogPostAdded(b.getHeader(), b.isLocal());
}
});
}
}
@Override @Override
public void setOnBlogPostAddedListener(OnBlogPostAddedListener listener) { public void setOnBlogPostAddedListener(OnBlogPostAddedListener listener) {
this.listener = listener; this.listener = listener;
} }
void onBlogPostAdded(final BlogPostHeader h, final boolean local) {
listener.runOnUiThreadUnlessDestroyed(new Runnable() {
@Override
public void run() {
listener.onBlogPostAdded(h, local);
}
});
}
void onBlogRemoved() {
listener.runOnUiThreadUnlessDestroyed(new Runnable() {
@Override
public void run() {
listener.onBlogRemoved();
}
});
}
@Override @Override
public void loadBlogPosts(final GroupId groupId, public void loadBlogPosts(final GroupId groupId,
final ResultExceptionHandler<Collection<BlogPostItem>, DbException> handler) { final ResultExceptionHandler<Collection<BlogPostItem>, DbException> handler) {

View File

@@ -26,6 +26,7 @@ import java.util.logging.Logger;
import javax.inject.Inject; import javax.inject.Inject;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
public class BlogControllerImpl extends BaseControllerImpl public class BlogControllerImpl extends BaseControllerImpl
@@ -50,15 +51,15 @@ public class BlogControllerImpl extends BaseControllerImpl
} }
@Override @Override
public void onActivityResume() { public void onActivityStart() {
super.onStart(); // TODO: Should be called when activity starts. #609 super.onStart();
notificationManager.blockNotification(groupId); notificationManager.blockNotification(groupId);
notificationManager.clearBlogPostNotification(groupId); notificationManager.clearBlogPostNotification(groupId);
} }
@Override @Override
public void onActivityPause() { public void onActivityStop() {
super.onStop(); // TODO: Should be called when activity stops. #609 super.onStop();
notificationManager.unblockNotification(groupId); notificationManager.unblockNotification(groupId);
} }
@@ -75,20 +76,16 @@ public class BlogControllerImpl extends BaseControllerImpl
public void eventOccurred(Event e) { public void eventOccurred(Event e) {
if (groupId == null) throw new IllegalStateException(); if (groupId == null) throw new IllegalStateException();
if (e instanceof BlogPostAddedEvent) { if (e instanceof BlogPostAddedEvent) {
BlogPostAddedEvent s = (BlogPostAddedEvent) e; BlogPostAddedEvent b = (BlogPostAddedEvent) e;
if (s.getGroupId().equals(groupId)) { if (b.getGroupId().equals(groupId)) {
super.eventOccurred(e); LOG.info("Blog post added");
onBlogPostAdded(b.getHeader(), b.isLocal());
} }
} else if (e instanceof GroupRemovedEvent) { } else if (e instanceof GroupRemovedEvent) {
GroupRemovedEvent s = (GroupRemovedEvent) e; GroupRemovedEvent g = (GroupRemovedEvent) e;
if (s.getGroup().getId().equals(groupId)) { if (g.getGroup().getId().equals(groupId)) {
LOG.info("Blog removed"); LOG.info("Blog removed");
listener.runOnUiThreadUnlessDestroyed(new Runnable() { onBlogRemoved();
@Override
public void run() {
listener.onBlogRemoved();
}
});
} }
} }
} }
@@ -115,11 +112,15 @@ public class BlogControllerImpl extends BaseControllerImpl
@Override @Override
public void run() { public void run() {
try { try {
long now = System.currentTimeMillis();
LocalAuthor a = identityManager.getLocalAuthor(); LocalAuthor a = identityManager.getLocalAuthor();
Blog b = blogManager.getBlog(groupId); Blog b = blogManager.getBlog(groupId);
boolean ours = a.getId().equals(b.getAuthor().getId()); boolean ours = a.getId().equals(b.getAuthor().getId());
boolean removable = blogManager.canBeRemoved(groupId); boolean removable = blogManager.canBeRemoved(groupId);
BlogItem blog = new BlogItem(b, ours, removable); BlogItem blog = new BlogItem(b, ours, removable);
long duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO))
LOG.info("Loading blog took " + duration + " ms");
handler.onResult(blog); handler.onResult(blog);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) if (LOG.isLoggable(WARNING))
@@ -138,8 +139,12 @@ public class BlogControllerImpl extends BaseControllerImpl
@Override @Override
public void run() { public void run() {
try { try {
long now = System.currentTimeMillis();
Blog b = blogManager.getBlog(groupId); Blog b = blogManager.getBlog(groupId);
blogManager.removeBlog(b); blogManager.removeBlog(b);
long duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO))
LOG.info("Removing blog took " + duration + " ms");
handler.onResult(null); handler.onResult(null);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) if (LOG.isLoggable(WARNING))

View File

@@ -123,18 +123,13 @@ public class BlogFragment extends BaseFragment implements
public void onStart() { public void onStart() {
super.onStart(); super.onStart();
loadBlog(); loadBlog();
}
@Override
public void onResume() {
super.onResume();
loadBlogPosts(false); loadBlogPosts(false);
list.startPeriodicUpdate(); list.startPeriodicUpdate();
} }
@Override @Override
public void onPause() { public void onStop() {
super.onPause(); super.onStop();
list.stopPeriodicUpdate(); list.stopPeriodicUpdate();
} }
@@ -215,9 +210,11 @@ public class BlogFragment extends BaseFragment implements
adapter.add(post); adapter.add(post);
if (local) { if (local) {
list.scrollToPosition(0); list.scrollToPosition(0);
displaySnackbar(R.string.blogs_blog_post_created, false); displaySnackbar(R.string.blogs_blog_post_created,
false);
} else { } else {
displaySnackbar(R.string.blogs_blog_post_received, true); displaySnackbar(R.string.blogs_blog_post_received,
true);
} }
} }
@@ -236,11 +233,11 @@ public class BlogFragment extends BaseFragment implements
listener) { listener) {
@Override @Override
public void onResultUi(Collection<BlogPostItem> posts) { public void onResultUi(Collection<BlogPostItem> posts) {
if (posts.size() > 0) { if (posts.isEmpty()) {
list.showData();
} else {
adapter.addAll(posts); adapter.addAll(posts);
if (reload) list.scrollToPosition(0); if (reload) list.scrollToPosition(0);
} else {
list.showData();
} }
} }

View File

@@ -1,7 +1,6 @@
package org.briarproject.android.blogs; package org.briarproject.android.blogs;
import org.briarproject.android.controller.handler.ResultExceptionHandler; import org.briarproject.android.controller.handler.ResultExceptionHandler;
import org.briarproject.android.controller.handler.ResultHandler;
import org.briarproject.api.blogs.Blog; import org.briarproject.api.blogs.Blog;
import org.briarproject.api.db.DbException; import org.briarproject.api.db.DbException;
@@ -12,6 +11,6 @@ public interface FeedController extends BaseController {
void loadBlogPosts( void loadBlogPosts(
ResultExceptionHandler<Collection<BlogPostItem>, DbException> handler); ResultExceptionHandler<Collection<BlogPostItem>, DbException> handler);
void loadPersonalBlog(ResultHandler<Blog> resultHandler); void loadPersonalBlog(ResultExceptionHandler<Blog, DbException> handler);
} }

View File

@@ -2,14 +2,16 @@ package org.briarproject.android.blogs;
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.controller.handler.ResultHandler;
import org.briarproject.api.blogs.Blog; import org.briarproject.api.blogs.Blog;
import org.briarproject.api.blogs.BlogManager; import org.briarproject.api.blogs.BlogManager;
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.db.NoSuchGroupException; import org.briarproject.api.db.NoSuchGroupException;
import org.briarproject.api.db.NoSuchMessageException; import org.briarproject.api.db.NoSuchMessageException;
import org.briarproject.api.event.BlogPostAddedEvent;
import org.briarproject.api.event.Event;
import org.briarproject.api.event.EventBus; import org.briarproject.api.event.EventBus;
import org.briarproject.api.event.GroupRemovedEvent;
import org.briarproject.api.identity.Author; import org.briarproject.api.identity.Author;
import org.briarproject.api.identity.IdentityManager; import org.briarproject.api.identity.IdentityManager;
import org.briarproject.api.lifecycle.LifecycleManager; import org.briarproject.api.lifecycle.LifecycleManager;
@@ -52,15 +54,28 @@ public class FeedControllerImpl extends BaseControllerImpl
notificationManager.unblockAllBlogPostNotifications(); notificationManager.unblockAllBlogPostNotifications();
} }
@Override
public void eventOccurred(Event e) {
if (e instanceof BlogPostAddedEvent) {
BlogPostAddedEvent b = (BlogPostAddedEvent) e;
LOG.info("Blog post added");
onBlogPostAdded(b.getHeader(), b.isLocal());
} else if (e instanceof GroupRemovedEvent) {
GroupRemovedEvent g = (GroupRemovedEvent) e;
if (g.getGroup().getClientId().equals(blogManager.getClientId())) {
LOG.info("Blog removed");
onBlogRemoved();
}
}
}
@Override @Override
public void loadBlogPosts( public void loadBlogPosts(
final ResultExceptionHandler<Collection<BlogPostItem>, DbException> handler) { final ResultExceptionHandler<Collection<BlogPostItem>, DbException> handler) {
LOG.info("Loading all blog posts...");
runOnDbThread(new Runnable() { runOnDbThread(new Runnable() {
@Override @Override
public void run() { public void run() {
try { try {
// load blog posts
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
Collection<BlogPostItem> posts = new ArrayList<>(); Collection<BlogPostItem> posts = new ArrayList<>();
for (Blog b : blogManager.getBlogs()) { for (Blog b : blogManager.getBlogs()) {
@@ -85,24 +100,23 @@ public class FeedControllerImpl extends BaseControllerImpl
} }
@Override @Override
public void loadPersonalBlog(final ResultHandler<Blog> resultHandler) { public void loadPersonalBlog(
LOG.info("Loading personal blog..."); final ResultExceptionHandler<Blog, DbException> handler) {
runOnDbThread(new Runnable() { runOnDbThread(new Runnable() {
@Override @Override
public void run() { public void run() {
try { try {
// load blog posts
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
Author a = identityManager.getLocalAuthor(); Author a = identityManager.getLocalAuthor();
Blog b = blogManager.getPersonalBlog(a); Blog b = blogManager.getPersonalBlog(a);
long duration = System.currentTimeMillis() - now; long duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO)) if (LOG.isLoggable(INFO))
LOG.info("Loading pers. blog took " + duration + " ms"); LOG.info("Loading blog took " + duration + " ms");
resultHandler.onResult(b); handler.onResult(b);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e); LOG.log(WARNING, e.toString(), e);
resultHandler.onResult(null); handler.onException(e);
} }
} }
}); });

View File

@@ -20,7 +20,6 @@ import org.briarproject.android.ActivityComponent;
import org.briarproject.android.blogs.BaseController.OnBlogPostAddedListener; import org.briarproject.android.blogs.BaseController.OnBlogPostAddedListener;
import org.briarproject.android.blogs.BlogPostAdapter.OnBlogPostClickListener; import org.briarproject.android.blogs.BlogPostAdapter.OnBlogPostClickListener;
import org.briarproject.android.controller.handler.UiResultExceptionHandler; import org.briarproject.android.controller.handler.UiResultExceptionHandler;
import org.briarproject.android.controller.handler.UiResultHandler;
import org.briarproject.android.fragment.BaseFragment; import org.briarproject.android.fragment.BaseFragment;
import org.briarproject.android.view.BriarRecyclerView; import org.briarproject.android.view.BriarRecyclerView;
import org.briarproject.api.blogs.Blog; import org.briarproject.api.blogs.Blog;
@@ -99,40 +98,56 @@ public class FeedFragment extends BaseFragment implements
public void onStart() { public void onStart() {
super.onStart(); super.onStart();
feedController.onStart(); feedController.onStart();
feedController.loadPersonalBlog( loadPersonalBlog();
new UiResultHandler<Blog>(listener) { loadBlogPosts(false);
@Override
public void onResultUi(Blog b) {
personalBlog = b;
}
});
feedController.loadBlogPosts(
new UiResultExceptionHandler<Collection<BlogPostItem>, DbException>(
listener) {
@Override
public void onResultUi(Collection<BlogPostItem> posts) {
if (posts.isEmpty()) {
list.showData();
} else {
adapter.addAll(posts);
}
}
@Override
public void onExceptionUi(DbException exception) {
// TODO
}
});
list.startPeriodicUpdate();
} }
@Override @Override
public void onStop() { public void onStop() {
super.onStop(); super.onStop();
feedController.onStop(); feedController.onStop();
adapter.clear();
list.showProgressBar();
list.stopPeriodicUpdate(); list.stopPeriodicUpdate();
// TODO save list position in database/preferences? // TODO save list position in database/preferences?
} }
private void loadPersonalBlog() {
feedController.loadPersonalBlog(
new UiResultExceptionHandler<Blog, DbException>(listener) {
@Override
public void onResultUi(Blog b) {
personalBlog = b;
}
@Override
public void onExceptionUi(DbException exception) {
// TODO: Decide how to handle errors in the UI
finish();
}
});
}
private void loadBlogPosts(final boolean clear) {
feedController.loadBlogPosts(
new UiResultExceptionHandler<Collection<BlogPostItem>, DbException>(
listener) {
@Override
public void onResultUi(Collection<BlogPostItem> posts) {
if (clear) adapter.setItems(posts);
else adapter.addAll(posts);
if (posts.isEmpty()) list.showData();
}
@Override
public void onExceptionUi(DbException e) {
// TODO: Decide how to handle errors in the UI
finish();
}
});
list.startPeriodicUpdate();
}
@Override @Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.blogs_feed_actions, menu); inflater.inflate(R.menu.blogs_feed_actions, menu);
@@ -185,9 +200,11 @@ public class FeedFragment extends BaseFragment implements
showSnackBar(R.string.blogs_blog_post_received); showSnackBar(R.string.blogs_blog_post_received);
} }
} }
@Override @Override
public void onExceptionUi(DbException exception) { public void onExceptionUi(DbException exception) {
// TODO: Decide how to handle errors in the UI // TODO: Decide how to handle errors in the UI
finish();
} }
} }
); );
@@ -234,6 +251,6 @@ public class FeedFragment extends BaseFragment implements
@Override @Override
public void onBlogRemoved() { public void onBlogRemoved() {
finish(); loadBlogPosts(true);
} }
} }

View File

@@ -37,9 +37,7 @@ public class RssFeedManageActivity extends BriarActivity
private BriarRecyclerView list; private BriarRecyclerView list;
private RssFeedAdapter adapter; private RssFeedAdapter adapter;
private GroupId groupId;
// Fields that are accessed from background threads must be volatile
private volatile GroupId groupId = null;
@Inject @Inject
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
@@ -65,11 +63,18 @@ public class RssFeedManageActivity extends BriarActivity
} }
@Override @Override
public void onResume() { public void onStart() {
super.onResume(); super.onStart();
loadFeeds(); loadFeeds();
} }
@Override
public void onStop() {
super.onStop();
adapter.clear();
list.showProgressBar();
}
@Override @Override
public boolean onCreateOptionsMenu(Menu menu) { public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater(); MenuInflater inflater = getMenuInflater();
@@ -139,7 +144,7 @@ public class RssFeedManageActivity extends BriarActivity
runOnUiThreadUnlessDestroyed(new Runnable() { runOnUiThreadUnlessDestroyed(new Runnable() {
@Override @Override
public void run() { public void run() {
if (feeds.size() == 0) list.showData(); if (feeds.isEmpty()) list.showData();
else adapter.addAll(feeds); else adapter.addAll(feeds);
} }
}); });

View File

@@ -94,15 +94,15 @@ public class WriteBlogPostActivity extends BriarActivity
} }
@Override @Override
public void onPause() { public void onStart() {
super.onPause(); super.onStart();
notificationManager.unblockNotification(groupId); notificationManager.blockNotification(groupId);
} }
@Override @Override
public void onResume() { public void onStop() {
super.onResume(); super.onStop();
notificationManager.blockNotification(groupId); notificationManager.unblockNotification(groupId);
} }
@Override @Override

View File

@@ -13,7 +13,6 @@ import org.briarproject.R;
import org.briarproject.android.util.BriarAdapter; import org.briarproject.android.util.BriarAdapter;
import org.briarproject.api.contact.ContactId; import org.briarproject.api.contact.ContactId;
import org.briarproject.api.identity.Author; import org.briarproject.api.identity.Author;
import org.briarproject.api.sync.GroupId;
import org.briarproject.util.StringUtils; import org.briarproject.util.StringUtils;
import im.delight.android.identicons.IdenticonDrawable; import im.delight.android.identicons.IdenticonDrawable;
@@ -90,17 +89,6 @@ public abstract class BaseContactListAdapter<VH extends BaseContactListAdapter.B
return INVALID_POSITION; // Not found return INVALID_POSITION; // Not found
} }
int findItemPosition(GroupId g) {
int count = getItemCount();
for (int i = 0; i < count; i++) {
ContactListItem item = getItemAt(i);
if (item != null && item.getGroupId().equals(g)) {
return i;
}
}
return INVALID_POSITION; // Not found
}
public static class BaseContactHolder extends RecyclerView.ViewHolder { public static class BaseContactHolder extends RecyclerView.ViewHolder {
public final ViewGroup layout; public final ViewGroup layout;

View File

@@ -170,8 +170,8 @@ public class ContactListFragment extends BaseFragment implements EventListener {
} }
@Override @Override
public void onResume() { public void onStart() {
super.onResume(); super.onStart();
notificationManager.blockAllContactNotifications(); notificationManager.blockAllContactNotifications();
notificationManager.clearAllContactNotifications(); notificationManager.clearAllContactNotifications();
eventBus.addListener(this); eventBus.addListener(this);
@@ -180,8 +180,8 @@ public class ContactListFragment extends BaseFragment implements EventListener {
} }
@Override @Override
public void onPause() { public void onStop() {
super.onPause(); super.onStop();
eventBus.removeListener(this); eventBus.removeListener(this);
notificationManager.unblockAllContactNotifications(); notificationManager.unblockAllContactNotifications();
adapter.clear(); adapter.clear();
@@ -213,10 +213,10 @@ public class ContactListFragment extends BaseFragment implements EventListener {
// Continue // Continue
} }
} }
displayContacts(contacts);
long duration = System.currentTimeMillis() - now; long duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO)) if (LOG.isLoggable(INFO))
LOG.info("Full load took " + duration + " ms"); LOG.info("Full load took " + duration + " ms");
displayContacts(contacts);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e); LOG.log(WARNING, e.toString(), e);
@@ -229,7 +229,7 @@ public class ContactListFragment extends BaseFragment implements EventListener {
listener.runOnUiThreadUnlessDestroyed(new Runnable() { listener.runOnUiThreadUnlessDestroyed(new Runnable() {
@Override @Override
public void run() { public void run() {
if (contacts.size() == 0) list.showData(); if (contacts.isEmpty()) list.showData();
else adapter.addAll(contacts); else adapter.addAll(contacts);
} }
}); });
@@ -238,40 +238,45 @@ public class ContactListFragment extends BaseFragment implements EventListener {
@Override @Override
public void eventOccurred(Event e) { public void eventOccurred(Event e) {
if (e instanceof ContactStatusChangedEvent) { if (e instanceof ContactStatusChangedEvent) {
LOG.info("Contact Status changed, reloading"); ContactStatusChangedEvent c = (ContactStatusChangedEvent) e;
// is also broadcast when contact was added if (c.isActive()) {
loadContacts(); LOG.info("Contact activated, reloading");
loadContacts();
} else {
LOG.info("Contact deactivated, removing item");
removeItem(c.getContactId());
}
} else if (e instanceof ContactConnectedEvent) { } else if (e instanceof ContactConnectedEvent) {
setConnected(((ContactConnectedEvent) e).getContactId(), true); setConnected(((ContactConnectedEvent) e).getContactId(), true);
} else if (e instanceof ContactDisconnectedEvent) { } else if (e instanceof ContactDisconnectedEvent) {
setConnected(((ContactDisconnectedEvent) e).getContactId(), false); setConnected(((ContactDisconnectedEvent) e).getContactId(), false);
} else if (e instanceof ContactRemovedEvent) { } else if (e instanceof ContactRemovedEvent) {
LOG.info("Contact removed"); LOG.info("Contact removed, removing item");
removeItem(((ContactRemovedEvent) e).getContactId()); removeItem(((ContactRemovedEvent) e).getContactId());
} else if (e instanceof PrivateMessageReceivedEvent) { } else if (e instanceof PrivateMessageReceivedEvent) {
LOG.info("Message received, update contact"); LOG.info("Private message received, updating item");
PrivateMessageReceivedEvent p = (PrivateMessageReceivedEvent) e; PrivateMessageReceivedEvent p = (PrivateMessageReceivedEvent) e;
PrivateMessageHeader h = p.getMessageHeader(); PrivateMessageHeader h = p.getMessageHeader();
updateItem(p.getGroupId(), ConversationItem.from(h)); updateItem(p.getContactId(), ConversationItem.from(h));
} else if (e instanceof IntroductionRequestReceivedEvent) { } else if (e instanceof IntroductionRequestReceivedEvent) {
LOG.info("Introduction Request received, update contact"); LOG.info("Introduction request received, updating item");
IntroductionRequestReceivedEvent m = IntroductionRequestReceivedEvent m =
(IntroductionRequestReceivedEvent) e; (IntroductionRequestReceivedEvent) e;
IntroductionRequest ir = m.getIntroductionRequest(); IntroductionRequest ir = m.getIntroductionRequest();
updateItem(m.getContactId(), ConversationItem.from(ir)); updateItem(m.getContactId(), ConversationItem.from(ir));
} else if (e instanceof IntroductionResponseReceivedEvent) { } else if (e instanceof IntroductionResponseReceivedEvent) {
LOG.info("Introduction Response received, update contact"); LOG.info("Introduction response received, updating item");
IntroductionResponseReceivedEvent m = IntroductionResponseReceivedEvent m =
(IntroductionResponseReceivedEvent) e; (IntroductionResponseReceivedEvent) e;
IntroductionResponse ir = m.getIntroductionResponse(); IntroductionResponse ir = m.getIntroductionResponse();
updateItem(m.getContactId(), ConversationItem.from(ir)); updateItem(m.getContactId(), ConversationItem.from(ir));
} else if (e instanceof InvitationRequestReceivedEvent) { } else if (e instanceof InvitationRequestReceivedEvent) {
LOG.info("Invitation Request received, update contact"); LOG.info("Invitation request received, updating item");
InvitationRequestReceivedEvent m = (InvitationRequestReceivedEvent) e; InvitationRequestReceivedEvent m = (InvitationRequestReceivedEvent) e;
InvitationRequest ir = m.getRequest(); InvitationRequest ir = m.getRequest();
updateItem(m.getContactId(), ConversationItem.from(ir)); updateItem(m.getContactId(), ConversationItem.from(ir));
} else if (e instanceof InvitationResponseReceivedEvent) { } else if (e instanceof InvitationResponseReceivedEvent) {
LOG.info("Invitation Response received, update contact"); LOG.info("Invitation response received, updating item");
InvitationResponseReceivedEvent m = InvitationResponseReceivedEvent m =
(InvitationResponseReceivedEvent) e; (InvitationResponseReceivedEvent) e;
InvitationResponse ir = m.getResponse(); InvitationResponse ir = m.getResponse();
@@ -293,20 +298,6 @@ public class ContactListFragment extends BaseFragment implements EventListener {
}); });
} }
private void updateItem(final GroupId g, final ConversationItem m) {
listener.runOnUiThreadUnlessDestroyed(new Runnable() {
@Override
public void run() {
int position = adapter.findItemPosition(g);
ContactListItem item = adapter.getItemAt(position);
if (item != null) {
item.addMessage(m);
adapter.updateItemAt(position, item);
}
}
});
}
private void removeItem(final ContactId c) { private void removeItem(final ContactId c) {
listener.runOnUiThreadUnlessDestroyed(new Runnable() { listener.runOnUiThreadUnlessDestroyed(new Runnable() {
@Override @Override

View File

@@ -34,7 +34,6 @@ import org.briarproject.android.view.TextInputView;
import org.briarproject.android.view.TextInputView.TextInputListener; import org.briarproject.android.view.TextInputView.TextInputListener;
import org.briarproject.api.FormatException; import org.briarproject.api.FormatException;
import org.briarproject.api.blogs.BlogSharingManager; import org.briarproject.api.blogs.BlogSharingManager;
import org.briarproject.api.clients.BaseMessageHeader;
import org.briarproject.api.clients.SessionId; import org.briarproject.api.clients.SessionId;
import org.briarproject.api.contact.Contact; import org.briarproject.api.contact.Contact;
import org.briarproject.api.contact.ContactId; import org.briarproject.api.contact.ContactId;
@@ -42,7 +41,6 @@ import org.briarproject.api.contact.ContactManager;
import org.briarproject.api.crypto.CryptoExecutor; import org.briarproject.api.crypto.CryptoExecutor;
import org.briarproject.api.db.DbException; import org.briarproject.api.db.DbException;
import org.briarproject.api.db.NoSuchContactException; import org.briarproject.api.db.NoSuchContactException;
import org.briarproject.api.db.NoSuchMessageException;
import org.briarproject.api.event.ContactConnectedEvent; import org.briarproject.api.event.ContactConnectedEvent;
import org.briarproject.api.event.ContactDisconnectedEvent; import org.briarproject.api.event.ContactDisconnectedEvent;
import org.briarproject.api.event.ContactRemovedEvent; import org.briarproject.api.event.ContactRemovedEvent;
@@ -150,7 +148,6 @@ public class ConversationActivity extends BriarActivity
private volatile ContactId contactId = null; private volatile ContactId contactId = null;
private volatile String contactName = null; private volatile String contactName = null;
private volatile byte[] contactIdenticonKey = null; private volatile byte[] contactIdenticonKey = null;
private volatile boolean connected = false;
@SuppressWarnings("ConstantConditions") @SuppressWarnings("ConstantConditions")
@Override @Override
@@ -214,18 +211,19 @@ public class ConversationActivity extends BriarActivity
} }
@Override @Override
public void onResume() { public void onStart() {
super.onResume(); super.onStart();
eventBus.addListener(this); eventBus.addListener(this);
notificationManager.blockNotification(groupId); notificationManager.blockNotification(groupId);
notificationManager.clearPrivateMessageNotification(groupId); notificationManager.clearPrivateMessageNotification(groupId);
loadData(); loadContactDetails();
loadMessages();
list.startPeriodicUpdate(); list.startPeriodicUpdate();
} }
@Override @Override
public void onPause() { public void onStop() {
super.onPause(); super.onStop();
eventBus.removeListener(this); eventBus.removeListener(this);
notificationManager.unblockNotification(groupId); notificationManager.unblockNotification(groupId);
list.stopPeriodicUpdate(); list.stopPeriodicUpdate();
@@ -277,7 +275,7 @@ public class ConversationActivity extends BriarActivity
finish(); finish();
} }
private void loadData() { private void loadContactDetails() {
runOnDbThread(new Runnable() { runOnDbThread(new Runnable() {
@Override @Override
public void run() { public void run() {
@@ -291,13 +289,12 @@ public class ConversationActivity extends BriarActivity
contactIdenticonKey = contactIdenticonKey =
contact.getAuthor().getId().getBytes(); contact.getAuthor().getId().getBytes();
} }
connected = connectionRegistry.isConnected(contactId); boolean connected =
connectionRegistry.isConnected(contactId);
long duration = System.currentTimeMillis() - now; long duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO)) if (LOG.isLoggable(INFO))
LOG.info("Loading contact took " + duration + " ms"); LOG.info("Loading contact took " + duration + " ms");
displayContactDetails(); displayContactDetails(connected);
// Load the messages here to make sure we have a contactId
loadMessages();
} catch (NoSuchContactException e) { } catch (NoSuchContactException e) {
finishOnUiThread(); finishOnUiThread();
} catch (DbException e) { } catch (DbException e) {
@@ -308,7 +305,7 @@ public class ConversationActivity extends BriarActivity
}); });
} }
private void displayContactDetails() { private void displayContactDetails(final boolean connected) {
runOnUiThreadUnlessDestroyed(new Runnable() { runOnUiThreadUnlessDestroyed(new Runnable() {
@Override @Override
public void run() { public void run() {
@@ -359,7 +356,7 @@ public class ConversationActivity extends BriarActivity
invitations.addAll(blogInvitations); invitations.addAll(blogInvitations);
long duration = System.currentTimeMillis() - now; long duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO)) if (LOG.isLoggable(INFO))
LOG.info("Loading headers took " + duration + " ms"); LOG.info("Loading messages took " + duration + " ms");
displayMessages(headers, introductions, invitations); displayMessages(headers, introductions, invitations);
} catch (NoSuchContactException e) { } catch (NoSuchContactException e) {
finishOnUiThread(); finishOnUiThread();
@@ -378,13 +375,12 @@ public class ConversationActivity extends BriarActivity
@Override @Override
public void run() { public void run() {
textInputView.setSendButtonEnabled(true); textInputView.setSendButtonEnabled(true);
if (headers.isEmpty() && introductions.isEmpty() && int size = headers.size() + introductions.size() +
invitations.isEmpty()) { invitations.size();
// we have no messages, if (size == 0) {
// so let the list know to hide progress bar
list.showData(); list.showData();
} else { } else {
List<ConversationItem> items = new ArrayList<>(); List<ConversationItem> items = new ArrayList<>(size);
for (PrivateMessageHeader h : headers) { for (PrivateMessageHeader h : headers) {
ConversationMessageItem item = ConversationItem.from(h); ConversationMessageItem item = ConversationItem.from(h);
byte[] body = bodyCache.get(h.getId()); byte[] body = bodyCache.get(h.getId());
@@ -392,28 +388,26 @@ public class ConversationActivity extends BriarActivity
else item.setBody(body); else item.setBody(body);
items.add(item); items.add(item);
} }
for (IntroductionMessage m : introductions) { for (IntroductionMessage im : introductions) {
ConversationItem item; if (im instanceof IntroductionRequest) {
if (m instanceof IntroductionRequest) { IntroductionRequest ir = (IntroductionRequest) im;
item = ConversationItem items.add(ConversationItem.from(ir));
.from((IntroductionRequest) m);
} else { } else {
item = ConversationItem IntroductionResponse ir = (IntroductionResponse) im;
.from(ConversationActivity.this,
contactName,
(IntroductionResponse) m);
}
items.add(item);
}
for (InvitationMessage i : invitations) {
if (i instanceof InvitationRequest) {
InvitationRequest r = (InvitationRequest) i;
items.add(ConversationItem.from(r));
} else if (i instanceof InvitationResponse) {
InvitationResponse r = (InvitationResponse) i;
items.add(ConversationItem items.add(ConversationItem
.from(ConversationActivity.this, .from(ConversationActivity.this,
contactName, r)); contactName, ir));
}
}
for (InvitationMessage im : invitations) {
if (im instanceof InvitationRequest) {
InvitationRequest ir = (InvitationRequest) im;
items.add(ConversationItem.from(ir));
} else if (im instanceof InvitationResponse) {
InvitationResponse ir = (InvitationResponse) im;
items.add(ConversationItem
.from(ConversationActivity.this,
contactName, ir));
} }
} }
adapter.addAll(items); adapter.addAll(items);
@@ -435,8 +429,6 @@ public class ConversationActivity extends BriarActivity
if (LOG.isLoggable(INFO)) if (LOG.isLoggable(INFO))
LOG.info("Loading body took " + duration + " ms"); LOG.info("Loading body took " + duration + " ms");
displayMessageBody(m, body); displayMessageBody(m, body);
} catch (NoSuchMessageException e) {
// The item will be removed when we get the event
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e); LOG.log(WARNING, e.toString(), e);
@@ -496,9 +488,10 @@ public class ConversationActivity extends BriarActivity
public void run() { public void run() {
try { try {
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
for (Map.Entry<MessageId, GroupId> e : unread.entrySet()) for (Map.Entry<MessageId, GroupId> e : unread.entrySet()) {
messagingManager messagingManager.setReadFlag(e.getValue(), e.getKey(),
.setReadFlag(e.getValue(), e.getKey(), true); true);
}
long duration = System.currentTimeMillis() - now; long duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO)) if (LOG.isLoggable(INFO))
LOG.info("Marking read took " + duration + " ms"); LOG.info("Marking read took " + duration + " ms");
@@ -525,7 +518,6 @@ public class ConversationActivity extends BriarActivity
PrivateMessageHeader h = p.getMessageHeader(); PrivateMessageHeader h = p.getMessageHeader();
addConversationItem(ConversationItem.from(h)); addConversationItem(ConversationItem.from(h));
loadMessageBody(h.getId()); loadMessageBody(h.getId());
markMessageReadIfNew(h);
} }
} else if (e instanceof MessagesSentEvent) { } else if (e instanceof MessagesSentEvent) {
MessagesSentEvent m = (MessagesSentEvent) e; MessagesSentEvent m = (MessagesSentEvent) e;
@@ -543,15 +535,13 @@ public class ConversationActivity extends BriarActivity
ContactConnectedEvent c = (ContactConnectedEvent) e; ContactConnectedEvent c = (ContactConnectedEvent) e;
if (c.getContactId().equals(contactId)) { if (c.getContactId().equals(contactId)) {
LOG.info("Contact connected"); LOG.info("Contact connected");
connected = true; displayContactDetails(true);
displayContactDetails();
} }
} else if (e instanceof ContactDisconnectedEvent) { } else if (e instanceof ContactDisconnectedEvent) {
ContactDisconnectedEvent c = (ContactDisconnectedEvent) e; ContactDisconnectedEvent c = (ContactDisconnectedEvent) e;
if (c.getContactId().equals(contactId)) { if (c.getContactId().equals(contactId)) {
LOG.info("Contact disconnected"); LOG.info("Contact disconnected");
connected = false; displayContactDetails(false);
displayContactDetails();
} }
} else if (e instanceof IntroductionRequestReceivedEvent) { } else if (e instanceof IntroductionRequestReceivedEvent) {
IntroductionRequestReceivedEvent event = IntroductionRequestReceivedEvent event =
@@ -561,7 +551,6 @@ public class ConversationActivity extends BriarActivity
IntroductionRequest ir = event.getIntroductionRequest(); IntroductionRequest ir = event.getIntroductionRequest();
ConversationItem item = new ConversationIntroductionInItem(ir); ConversationItem item = new ConversationIntroductionInItem(ir);
addConversationItem(item); addConversationItem(item);
markMessageReadIfNew(ir);
} }
} else if (e instanceof IntroductionResponseReceivedEvent) { } else if (e instanceof IntroductionResponseReceivedEvent) {
IntroductionResponseReceivedEvent event = IntroductionResponseReceivedEvent event =
@@ -572,7 +561,6 @@ public class ConversationActivity extends BriarActivity
ConversationItem item = ConversationItem item =
ConversationItem.from(this, contactName, ir); ConversationItem.from(this, contactName, ir);
addConversationItem(item); addConversationItem(item);
markMessageReadIfNew(ir);
} }
} else if (e instanceof InvitationRequestReceivedEvent) { } else if (e instanceof InvitationRequestReceivedEvent) {
InvitationRequestReceivedEvent event = InvitationRequestReceivedEvent event =
@@ -582,7 +570,6 @@ public class ConversationActivity extends BriarActivity
InvitationRequest ir = event.getRequest(); InvitationRequest ir = event.getRequest();
ConversationItem item = ConversationItem.from(ir); ConversationItem item = ConversationItem.from(ir);
addConversationItem(item); addConversationItem(item);
markMessageReadIfNew(ir);
} }
} else if (e instanceof InvitationResponseReceivedEvent) { } else if (e instanceof InvitationResponseReceivedEvent) {
InvitationResponseReceivedEvent event = InvitationResponseReceivedEvent event =
@@ -593,46 +580,10 @@ public class ConversationActivity extends BriarActivity
ConversationItem item = ConversationItem item =
ConversationItem.from(this, contactName, ir); ConversationItem.from(this, contactName, ir);
addConversationItem(item); addConversationItem(item);
markMessageReadIfNew(ir);
} }
} }
} }
private void markMessageReadIfNew(final BaseMessageHeader h) {
runOnUiThreadUnlessDestroyed(new Runnable() {
@Override
public void run() {
ConversationItem item = adapter.getLastItem();
if (item != null) {
// Mark the message read if it's the newest message
long lastMsgTime = item.getTime();
long newMsgTime = h.getTimestamp();
if (newMsgTime > lastMsgTime)
markNewMessageRead(h.getGroupId(), h.getId());
else loadMessages();
} else {
// mark the message as read as well if it is the first one
markNewMessageRead(h.getGroupId(), h.getId());
}
}
});
}
private void markNewMessageRead(final GroupId g, final MessageId m) {
runOnDbThread(new Runnable() {
@Override
public void run() {
try {
messagingManager.setReadFlag(g, m, true);
loadMessages();
} catch (DbException e) {
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
}
}
});
}
private void markMessages(final Collection<MessageId> messageIds, private void markMessages(final Collection<MessageId> messageIds,
final boolean sent, final boolean seen) { final boolean sent, final boolean seen) {
runOnUiThreadUnlessDestroyed(new Runnable() { runOnUiThreadUnlessDestroyed(new Runnable() {
@@ -654,7 +605,6 @@ public class ConversationActivity extends BriarActivity
@Override @Override
public void onSendClick(String text) { public void onSendClick(String text) {
markMessagesRead();
if (text.equals("")) return; if (text.equals("")) return;
long timestamp = System.currentTimeMillis(); long timestamp = System.currentTimeMillis();
timestamp = Math.max(timestamp, getMinTimestampForNewMessage()); timestamp = Math.max(timestamp, getMinTimestampForNewMessage());

View File

@@ -6,9 +6,9 @@ public interface ActivityLifecycleController {
void onActivityCreate(Activity activity); void onActivityCreate(Activity activity);
void onActivityResume(); void onActivityStart();
void onActivityPause(); void onActivityStop();
void onActivityDestroy(); void onActivityDestroy();
} }

View File

@@ -19,18 +19,18 @@ public class BriarControllerImpl implements BriarController {
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(BriarControllerImpl.class.getName()); Logger.getLogger(BriarControllerImpl.class.getName());
@Inject private final BriarServiceConnection serviceConnection;
BriarServiceConnection serviceConnection; private final DatabaseConfig databaseConfig;
@Inject private final Activity activity;
DatabaseConfig databaseConfig;
@Inject
Activity activity;
private boolean bound = false; private boolean bound = false;
@Inject @Inject
public BriarControllerImpl() { BriarControllerImpl(BriarServiceConnection serviceConnection,
DatabaseConfig databaseConfig, Activity activity) {
this.serviceConnection = serviceConnection;
this.databaseConfig = databaseConfig;
this.activity = activity;
} }
@Override @Override
@@ -40,13 +40,11 @@ public class BriarControllerImpl implements BriarController {
} }
@Override @Override
@CallSuper public void onActivityStart() {
public void onActivityResume() {
} }
@Override @Override
@CallSuper public void onActivityStop() {
public void onActivityPause() {
} }
@Override @Override

View File

@@ -57,12 +57,12 @@ public class NavDrawerControllerImpl extends DbControllerImpl
} }
@Override @Override
public void onActivityResume() { public void onActivityStart() {
eventBus.addListener(this); eventBus.addListener(this);
} }
@Override @Override
public void onActivityPause() { public void onActivityStop() {
eventBus.removeListener(this); eventBus.removeListener(this);
} }

View File

@@ -1,6 +1,7 @@
package org.briarproject.android.forum; package org.briarproject.android.forum;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.LayoutRes; import android.support.annotation.LayoutRes;
@@ -98,9 +99,8 @@ public class ForumActivity extends
@Override @Override
public boolean onOptionsItemSelected(final MenuItem item) { public boolean onOptionsItemSelected(final MenuItem item) {
ActivityOptionsCompat options = ActivityOptionsCompat options = makeCustomAnimation(this,
makeCustomAnimation(this, android.R.anim.slide_in_left, android.R.anim.slide_in_left, android.R.anim.slide_out_right);
android.R.anim.slide_out_right);
// Handle presses on the action bar items // Handle presses on the action bar items
switch (item.getItemId()) { switch (item.getItemId()) {
case R.id.action_forum_compose_post: case R.id.action_forum_compose_post:
@@ -110,9 +110,8 @@ public class ForumActivity extends
Intent i2 = new Intent(this, ShareForumActivity.class); Intent i2 = new Intent(this, ShareForumActivity.class);
i2.setFlags(FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_SINGLE_TOP); i2.setFlags(FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_SINGLE_TOP);
i2.putExtra(GROUP_ID, groupId.getBytes()); i2.putExtra(GROUP_ID, groupId.getBytes());
ActivityCompat ActivityCompat.startActivityForResult(this, i2,
.startActivityForResult(this, i2, REQUEST_FORUM_SHARED, REQUEST_FORUM_SHARED, options.toBundle());
options.toBundle());
return true; return true;
case R.id.action_forum_sharing_status: case R.id.action_forum_sharing_status:
Intent i3 = new Intent(this, SharingStatusForumActivity.class); Intent i3 = new Intent(this, SharingStatusForumActivity.class);
@@ -146,17 +145,14 @@ public class ForumActivity extends
} }
private void showUnsubscribeDialog() { private void showUnsubscribeDialog() {
DialogInterface.OnClickListener okListener = OnClickListener okListener = new OnClickListener() {
new DialogInterface.OnClickListener() { @Override
@Override public void onClick(final DialogInterface dialog, int which) {
public void onClick(final DialogInterface dialog, deleteNamedGroup();
int which) { }
deleteNamedGroup(); };
} AlertDialog.Builder builder = new AlertDialog.Builder(
}; ForumActivity.this, R.style.BriarDialogTheme);
AlertDialog.Builder builder =
new AlertDialog.Builder(ForumActivity.this,
R.style.BriarDialogTheme);
builder.setTitle(getString(R.string.dialog_title_leave_forum)); builder.setTitle(getString(R.string.dialog_title_leave_forum));
builder.setMessage(getString(R.string.dialog_message_leave_forum)); builder.setMessage(getString(R.string.dialog_message_leave_forum));
builder.setNegativeButton(R.string.dialog_button_leave, okListener); builder.setNegativeButton(R.string.dialog_button_leave, okListener);
@@ -171,14 +167,11 @@ public class ForumActivity extends
@Override @Override
public void onResultUi(Void v) { public void onResultUi(Void v) {
Toast.makeText(ForumActivity.this, Toast.makeText(ForumActivity.this,
R.string.forum_left_toast, R.string.forum_left_toast, LENGTH_SHORT).show();
LENGTH_SHORT)
.show();
} }
@Override @Override
public void onExceptionUi( public void onExceptionUi(DbException exception) {
DbException exception) {
// TODO proper error handling // TODO proper error handling
finish(); finish();
} }

View File

@@ -28,8 +28,8 @@ import java.util.logging.Logger;
import javax.inject.Inject; import javax.inject.Inject;
public class ForumControllerImpl public class ForumControllerImpl extends
extends ThreadListControllerImpl<Forum, ForumItem, ForumPostHeader, ForumPost> ThreadListControllerImpl<Forum, ForumItem, ForumPostHeader, ForumPost>
implements ForumController { implements ForumController {
private static final Logger LOG = private static final Logger LOG =
@@ -49,8 +49,8 @@ public class ForumControllerImpl
} }
@Override @Override
public void onActivityResume() { public void onActivityStart() {
super.onActivityResume(); super.onActivityStart();
notificationManager.clearForumPostNotification(getGroupId()); notificationManager.clearForumPostNotification(getGroupId());
} }
@@ -59,7 +59,7 @@ public class ForumControllerImpl
super.eventOccurred(e); super.eventOccurred(e);
if (e instanceof ForumPostReceivedEvent) { if (e instanceof ForumPostReceivedEvent) {
final ForumPostReceivedEvent pe = (ForumPostReceivedEvent) e; ForumPostReceivedEvent pe = (ForumPostReceivedEvent) e;
if (pe.getGroupId().equals(getGroupId())) { if (pe.getGroupId().equals(getGroupId())) {
LOG.info("Forum post received, adding..."); LOG.info("Forum post received, adding...");
final ForumPostHeader fph = pe.getForumPostHeader(); final ForumPostHeader fph = pe.getForumPostHeader();
@@ -102,9 +102,8 @@ public class ForumControllerImpl
@Override @Override
protected ForumPost createLocalMessage(String body, long timestamp, protected ForumPost createLocalMessage(String body, long timestamp,
@Nullable MessageId parentId, LocalAuthor author) { @Nullable MessageId parentId, LocalAuthor author) {
return forumManager return forumManager.createLocalPost(getGroupId(), body, timestamp,
.createLocalPost(getGroupId(), body, timestamp, parentId, parentId, author);
author);
} }
@Override @Override

View File

@@ -111,9 +111,8 @@ public class ForumListFragment extends BaseEventFragment implements
} }
@Override @Override
public void onResume() { public void onStart() {
super.onResume(); super.onStart();
notificationManager.blockAllForumPostNotifications(); notificationManager.blockAllForumPostNotifications();
notificationManager.clearAllForumPostNotifications(); notificationManager.clearAllForumPostNotifications();
loadForums(); loadForums();
@@ -122,9 +121,8 @@ public class ForumListFragment extends BaseEventFragment implements
} }
@Override @Override
public void onPause() { public void onStop() {
super.onPause(); super.onStop();
notificationManager.unblockAllForumPostNotifications(); notificationManager.unblockAllForumPostNotifications();
adapter.clear(); adapter.clear();
list.showProgressBar(); list.showProgressBar();
@@ -156,7 +154,6 @@ public class ForumListFragment extends BaseEventFragment implements
@Override @Override
public void run() { public void run() {
try { try {
// load forums
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
Collection<ForumListItem> forums = new ArrayList<>(); Collection<ForumListItem> forums = new ArrayList<>();
for (Forum f : forumManager.getForums()) { for (Forum f : forumManager.getForums()) {
@@ -168,10 +165,10 @@ public class ForumListFragment extends BaseEventFragment implements
// Continue // Continue
} }
} }
displayForums(forums);
long duration = System.currentTimeMillis() - now; long duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO)) if (LOG.isLoggable(INFO))
LOG.info("Full load took " + duration + " ms"); LOG.info("Full load took " + duration + " ms");
displayForums(forums);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e); LOG.log(WARNING, e.toString(), e);
@@ -184,8 +181,8 @@ public class ForumListFragment extends BaseEventFragment implements
listener.runOnUiThreadUnlessDestroyed(new Runnable() { listener.runOnUiThreadUnlessDestroyed(new Runnable() {
@Override @Override
public void run() { public void run() {
if (forums.size() > 0) adapter.addAll(forums); if (forums.isEmpty()) list.showData();
else list.showData(); else adapter.addAll(forums);
} }
}); });
} }
@@ -245,9 +242,10 @@ public class ForumListFragment extends BaseEventFragment implements
} }
} else if (e instanceof ForumPostReceivedEvent) { } else if (e instanceof ForumPostReceivedEvent) {
ForumPostReceivedEvent f = (ForumPostReceivedEvent) e; ForumPostReceivedEvent f = (ForumPostReceivedEvent) e;
LOG.info("Forum post added, updating..."); LOG.info("Forum post added, updating item");
updateItem(f.getGroupId(), f.getForumPostHeader()); updateItem(f.getGroupId(), f.getForumPostHeader());
} else if (e instanceof ForumInvitationReceivedEvent) { } else if (e instanceof ForumInvitationReceivedEvent) {
LOG.info("Forum invitation received, reloading available forums");
loadAvailableForums(); loadAvailableForums();
} }
} }

View File

@@ -12,14 +12,14 @@ public abstract class BaseEventFragment extends BaseFragment implements
protected volatile EventBus eventBus; protected volatile EventBus eventBus;
@Override @Override
public void onResume() { public void onStart() {
super.onResume(); super.onStart();
eventBus.addListener(this); eventBus.addListener(this);
} }
@Override @Override
public void onPause() { public void onStop() {
super.onPause(); super.onStop();
eventBus.removeListener(this); eventBus.removeListener(this);
} }
} }

View File

@@ -44,6 +44,7 @@ public abstract class BaseFragment extends Fragment
public interface BaseFragmentListener extends DestroyableContext { public interface BaseFragmentListener extends DestroyableContext {
@Deprecated
void runOnDbThread(Runnable runnable); void runOnDbThread(Runnable runnable);
@UiThread @UiThread

View File

@@ -155,14 +155,14 @@ public class SettingsFragment extends PreferenceFragmentCompat
} }
@Override @Override
public void onResume() { public void onStart() {
super.onResume(); super.onStart();
eventBus.addListener(this); eventBus.addListener(this);
} }
@Override @Override
public void onPause() { public void onStop() {
super.onPause(); super.onStop();
eventBus.removeListener(this); eventBus.removeListener(this);
} }

View File

@@ -1,19 +1,19 @@
package org.briarproject.android.introduction; package org.briarproject.android.introduction;
import android.content.Context; import android.content.Context;
import android.support.annotation.UiThread;
import android.view.View; import android.view.View;
import org.briarproject.android.contact.ContactListAdapter; import org.briarproject.android.contact.ContactListAdapter;
import org.briarproject.android.contact.ContactListItem; import org.briarproject.android.contact.ContactListItem;
import org.briarproject.api.identity.AuthorId; import org.briarproject.api.identity.AuthorId;
public class ContactChooserAdapter extends ContactListAdapter { @UiThread
class ContactChooserAdapter extends ContactListAdapter {
private AuthorId localAuthorId; private AuthorId localAuthorId;
public ContactChooserAdapter(Context context, ContactChooserAdapter(Context context, OnItemClickListener listener) {
OnItemClickListener listener) {
super(context, listener); super(context, listener);
} }
@@ -46,7 +46,7 @@ public class ContactChooserAdapter extends ContactListAdapter {
* *
* @param authorId The ID of the local Author * @param authorId The ID of the local Author
*/ */
public void setLocalAuthor(AuthorId authorId) { void setLocalAuthor(AuthorId authorId) {
localAuthorId = authorId; localAuthorId = authorId;
notifyDataSetChanged(); notifyDataSetChanged();
} }

View File

@@ -45,18 +45,18 @@ public class ContactChooserFragment extends BaseFragment {
private IntroductionActivity introductionActivity; private IntroductionActivity introductionActivity;
private BriarRecyclerView list; private BriarRecyclerView list;
private ContactChooserAdapter adapter; private ContactChooserAdapter adapter;
private int contactId; private ContactId contactId;
// Fields that are accessed from background threads must be volatile // Fields that are accessed from background threads must be volatile
protected volatile Contact c1; volatile Contact c1;
@Inject @Inject
protected volatile ContactManager contactManager; volatile ContactManager contactManager;
@Inject @Inject
protected volatile IdentityManager identityManager; volatile IdentityManager identityManager;
@Inject @Inject
protected volatile ConversationManager conversationManager; volatile ConversationManager conversationManager;
@Inject @Inject
protected volatile ConnectionRegistry connectionRegistry; volatile ConnectionRegistry connectionRegistry;
public static ContactChooserFragment newInstance() { public static ContactChooserFragment newInstance() {
@@ -87,9 +87,7 @@ public class ContactChooserFragment extends BaseFragment {
new ContactListAdapter.OnItemClickListener() { new ContactListAdapter.OnItemClickListener() {
@Override @Override
public void onItemClick(View view, ContactListItem item) { public void onItemClick(View view, ContactListItem item) {
if (c1 == null) { if (c1 == null) throw new IllegalStateException();
throw new RuntimeException("c1 not accountExists");
}
Contact c2 = item.getContact(); Contact c2 = item.getContact();
if (!c1.getLocalAuthorId() if (!c1.getLocalAuthorId()
.equals(c2.getLocalAuthorId())) { .equals(c2.getLocalAuthorId())) {
@@ -113,15 +111,14 @@ public class ContactChooserFragment extends BaseFragment {
} }
@Override @Override
public void onResume() { public void onStart() {
super.onResume(); super.onStart();
loadContacts(); loadContacts();
} }
@Override @Override
public void onPause() { public void onStop() {
super.onPause(); super.onStop();
adapter.clear(); adapter.clear();
list.showProgressBar(); list.showProgressBar();
} }
@@ -145,7 +142,7 @@ public class ContactChooserFragment extends BaseFragment {
AuthorId localAuthorId = AuthorId localAuthorId =
identityManager.getLocalAuthor().getId(); identityManager.getLocalAuthor().getId();
for (Contact c : contactManager.getActiveContacts()) { for (Contact c : contactManager.getActiveContacts()) {
if (c.getId().getInt() == contactId) { if (c.getId().equals(contactId)) {
c1 = c; c1 = c;
} else { } else {
ContactId id = c.getId(); ContactId id = c.getId();
@@ -176,7 +173,7 @@ public class ContactChooserFragment extends BaseFragment {
@Override @Override
public void run() { public void run() {
adapter.setLocalAuthor(localAuthorId); adapter.setLocalAuthor(localAuthorId);
if (contacts.size() == 0) list.showData(); if (contacts.isEmpty()) list.showData();
else adapter.addAll(contacts); else adapter.addAll(contacts);
} }
}); });

View File

@@ -14,6 +14,7 @@ import org.briarproject.android.ActivityComponent;
import org.briarproject.android.BriarActivity; import org.briarproject.android.BriarActivity;
import org.briarproject.android.fragment.BaseFragment; import org.briarproject.android.fragment.BaseFragment;
import org.briarproject.api.contact.Contact; import org.briarproject.api.contact.Contact;
import org.briarproject.api.contact.ContactId;
// TODO extend the BriarFragmentActivity ? // TODO extend the BriarFragmentActivity ?
public class IntroductionActivity extends BriarActivity implements public class IntroductionActivity extends BriarActivity implements
@@ -21,16 +22,16 @@ public class IntroductionActivity extends BriarActivity implements
public static final String CONTACT_ID = "briar.CONTACT_ID"; public static final String CONTACT_ID = "briar.CONTACT_ID";
private int contactId; private ContactId contactId;
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
Intent intent = getIntent(); Intent intent = getIntent();
contactId = intent.getIntExtra(CONTACT_ID, -1); int id = intent.getIntExtra(CONTACT_ID, -1);
if (contactId == -1) if (id == -1) throw new IllegalStateException("No ContactId");
throw new IllegalArgumentException("Wrong ContactId"); contactId = new ContactId(id);
setContentView(R.layout.activity_fragment_container); setContentView(R.layout.activity_fragment_container);
@@ -75,7 +76,7 @@ public class IntroductionActivity extends BriarActivity implements
} }
} }
int getContactId() { ContactId getContactId() {
return contactId; return contactId;
} }

View File

@@ -37,9 +37,13 @@ public class AddContactActivity extends BriarActivity
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(AddContactActivity.class.getName()); Logger.getLogger(AddContactActivity.class.getName());
@Inject protected CryptoComponent crypto; @Inject
@Inject protected InvitationTaskFactory invitationTaskFactory; CryptoComponent crypto;
@Inject protected ReferenceManager referenceManager; @Inject
InvitationTaskFactory invitationTaskFactory;
@Inject
ReferenceManager referenceManager;
private AddContactView view = null; private AddContactView view = null;
private InvitationTask task = null; private InvitationTask task = null;
private long taskHandle = -1; private long taskHandle = -1;
@@ -52,7 +56,8 @@ public class AddContactActivity extends BriarActivity
private String contactName = null; private String contactName = null;
// Fields that are accessed from background threads must be volatile // Fields that are accessed from background threads must be volatile
@Inject protected volatile IdentityManager identityManager; @Inject
volatile IdentityManager identityManager;
@Override @Override
public void onCreate(Bundle state) { public void onCreate(Bundle state) {
@@ -150,8 +155,8 @@ public class AddContactActivity extends BriarActivity
} }
@Override @Override
public void onResume() { public void onStart() {
super.onResume(); super.onStart();
view.populate(); view.populate();
} }

View File

@@ -40,15 +40,13 @@ public class KeyAgreementActivity extends BriarFragmentActivity implements
private static final int STEP_QR = 2; private static final int STEP_QR = 2;
@Inject @Inject
protected EventBus eventBus; EventBus eventBus;
private Toolbar toolbar;
// Fields that are accessed from background threads must be volatile // Fields that are accessed from background threads must be volatile
@Inject @Inject
protected volatile ContactExchangeTask contactExchangeTask; volatile ContactExchangeTask contactExchangeTask;
@Inject @Inject
protected volatile IdentityManager identityManager; volatile IdentityManager identityManager;
@Override @Override
public void injectActivity(ActivityComponent component) { public void injectActivity(ActivityComponent component) {
@@ -61,7 +59,7 @@ public class KeyAgreementActivity extends BriarFragmentActivity implements
super.onCreate(state); super.onCreate(state);
setContentView(R.layout.activity_plain); setContentView(R.layout.activity_plain);
toolbar = (Toolbar) findViewById(R.id.toolbar); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar); setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setDisplayHomeAsUpEnabled(true);
@@ -83,14 +81,14 @@ public class KeyAgreementActivity extends BriarFragmentActivity implements
} }
@Override @Override
public void onResume() { public void onStart() {
super.onResume(); super.onStart();
eventBus.addListener(this); eventBus.addListener(this);
} }
@Override @Override
protected void onPause() { protected void onStop() {
super.onPause(); super.onStop();
eventBus.removeListener(this); eventBus.removeListener(this);
} }

View File

@@ -162,25 +162,16 @@ public class ShowQrCodeFragment extends BaseEventFragment
} else { } else {
startListening(); startListening();
} }
}
@Override
public void onResume() {
super.onResume();
openCamera(); openCamera();
} }
@Override
public void onPause() {
super.onPause();
releaseCamera();
}
@Override @Override
public void onStop() { public void onStop() {
super.onStop(); super.onStop();
stopListening(); stopListening();
if (receiver != null) getActivity().unregisterReceiver(receiver); if (receiver != null) getActivity().unregisterReceiver(receiver);
releaseCamera();
} }
@UiThread @UiThread

View File

@@ -132,16 +132,16 @@ public class PanicPreferencesFragment extends PreferenceFragmentCompat
} }
@Override @Override
public void onResume() { public void onStart() {
super.onResume(); super.onStart();
getPreferenceScreen().getSharedPreferences() getPreferenceScreen().getSharedPreferences()
.registerOnSharedPreferenceChangeListener(this); .registerOnSharedPreferenceChangeListener(this);
showPanicApp(PanicResponder.getTriggerPackageName(getActivity())); showPanicApp(PanicResponder.getTriggerPackageName(getActivity()));
} }
@Override @Override
public void onPause() { public void onStop() {
super.onPause(); super.onStop();
getPreferenceScreen().getSharedPreferences() getPreferenceScreen().getSharedPreferences()
.unregisterOnSharedPreferenceChangeListener(this); .unregisterOnSharedPreferenceChangeListener(this);
} }

View File

@@ -27,8 +27,8 @@ import java.util.logging.Logger;
import javax.inject.Inject; import javax.inject.Inject;
public class GroupControllerImpl public class GroupControllerImpl extends
extends ThreadListControllerImpl<PrivateGroup, GroupMessageItem, GroupMessageHeader, GroupMessage> ThreadListControllerImpl<PrivateGroup, GroupMessageItem, GroupMessageHeader, GroupMessage>
implements GroupController { implements GroupController {
private static final Logger LOG = private static final Logger LOG =
@@ -48,8 +48,8 @@ public class GroupControllerImpl
} }
@Override @Override
public void onActivityResume() { public void onActivityStart() {
super.onActivityResume(); super.onActivityStart();
// TODO: Add new notification manager methods for private groups // TODO: Add new notification manager methods for private groups
} }
@@ -101,9 +101,8 @@ public class GroupControllerImpl
@Override @Override
protected GroupMessage createLocalMessage(String body, long timestamp, protected GroupMessage createLocalMessage(String body, long timestamp,
@Nullable MessageId parentId, LocalAuthor author) { @Nullable MessageId parentId, LocalAuthor author) {
return privateGroupManager return privateGroupManager.createLocalMessage(getGroupId(), body,
.createLocalMessage(getGroupId(), body, timestamp, parentId, timestamp, parentId, author);
author);
} }
@Override @Override

View File

@@ -1,56 +1,51 @@
package org.briarproject.android.privategroup.list; package org.briarproject.android.privategroup.list;
import org.briarproject.api.clients.MessageTracker.GroupCount;
import org.briarproject.api.identity.Author; import org.briarproject.api.identity.Author;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.privategroup.GroupMessageHeader; import org.briarproject.api.privategroup.GroupMessageHeader;
import org.briarproject.api.privategroup.PrivateGroup; import org.briarproject.api.privategroup.PrivateGroup;
import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.GroupId;
import org.jetbrains.annotations.NotNull;
// This class is not thread-safe // This class is not thread-safe
@NotNullByDefault
class GroupItem { class GroupItem {
private final PrivateGroup privateGroup; private final PrivateGroup privateGroup;
private int messageCount; private int messageCount, unreadCount;
private long lastUpdate; private long timestamp;
private int unreadCount;
private boolean dissolved; private boolean dissolved;
GroupItem(@NotNull PrivateGroup privateGroup, int messageCount, GroupItem(PrivateGroup privateGroup, GroupCount count, boolean dissolved) {
long lastUpdate, int unreadCount, boolean dissolved) {
this.privateGroup = privateGroup; this.privateGroup = privateGroup;
this.messageCount = messageCount; this.messageCount = count.getMsgCount();
this.lastUpdate = lastUpdate; this.unreadCount = count.getUnreadCount();
this.unreadCount = unreadCount; this.timestamp = count.getLatestMsgTime();
this.dissolved = dissolved; this.dissolved = dissolved;
} }
void addMessageHeader(GroupMessageHeader header) { void addMessageHeader(GroupMessageHeader header) {
messageCount++; messageCount++;
if (header.getTimestamp() > lastUpdate) { if (header.getTimestamp() > timestamp) {
lastUpdate = header.getTimestamp(); timestamp = header.getTimestamp();
} }
if (!header.isRead()) { if (!header.isRead()) {
unreadCount++; unreadCount++;
} }
} }
@NotNull
PrivateGroup getPrivateGroup() { PrivateGroup getPrivateGroup() {
return privateGroup; return privateGroup;
} }
@NotNull
GroupId getId() { GroupId getId() {
return privateGroup.getId(); return privateGroup.getId();
} }
@NotNull
Author getCreator() { Author getCreator() {
return privateGroup.getAuthor(); return privateGroup.getAuthor();
} }
@NotNull
String getName() { String getName() {
return privateGroup.getName(); return privateGroup.getName();
} }
@@ -63,8 +58,8 @@ class GroupItem {
return messageCount; return messageCount;
} }
long getLastUpdate() { long getTimestamp() {
return lastUpdate; return timestamp;
} }
int getUnreadCount() { int getUnreadCount() {

View File

@@ -38,7 +38,7 @@ class GroupListAdapter extends BriarAdapter<GroupItem, GroupViewHolder> {
public int compare(GroupItem a, GroupItem b) { public int compare(GroupItem a, GroupItem b) {
if (a == b) return 0; if (a == b) return 0;
// The group with the latest message comes first // The group with the latest message comes first
long aTime = a.getLastUpdate(), bTime = b.getLastUpdate(); long aTime = a.getTimestamp(), bTime = b.getTimestamp();
if (aTime > bTime) return -1; if (aTime > bTime) return -1;
if (aTime < bTime) return 1; if (aTime < bTime) return 1;
// Break ties by group name // Break ties by group name
@@ -50,7 +50,7 @@ class GroupListAdapter extends BriarAdapter<GroupItem, GroupViewHolder> {
@Override @Override
public boolean areContentsTheSame(GroupItem a, GroupItem b) { public boolean areContentsTheSame(GroupItem a, GroupItem b) {
return a.getMessageCount() == b.getMessageCount() && return a.getMessageCount() == b.getMessageCount() &&
a.getLastUpdate() == b.getLastUpdate() && a.getTimestamp() == b.getTimestamp() &&
a.getUnreadCount() == b.getUnreadCount() && a.getUnreadCount() == b.getUnreadCount() &&
a.isDissolved() == b.isDissolved(); a.isDissolved() == b.isDissolved();
} }

View File

@@ -31,6 +31,7 @@ public interface GroupListController extends DbController {
ResultExceptionHandler<Void, DbException> result); ResultExceptionHandler<Void, DbException> result);
interface GroupListListener extends DestroyableContext { interface GroupListListener extends DestroyableContext {
@UiThread @UiThread
void onGroupMessageAdded(GroupMessageHeader header); void onGroupMessageAdded(GroupMessageHeader header);

View File

@@ -8,6 +8,7 @@ import org.briarproject.android.controller.handler.ResultExceptionHandler;
import org.briarproject.api.clients.MessageTracker.GroupCount; import org.briarproject.api.clients.MessageTracker.GroupCount;
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.db.NoSuchGroupException;
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.EventListener; import org.briarproject.api.event.EventListener;
@@ -16,6 +17,7 @@ import org.briarproject.api.event.GroupMessageAddedEvent;
import org.briarproject.api.event.GroupRemovedEvent; import org.briarproject.api.event.GroupRemovedEvent;
import org.briarproject.api.identity.IdentityManager; import org.briarproject.api.identity.IdentityManager;
import org.briarproject.api.lifecycle.LifecycleManager; import org.briarproject.api.lifecycle.LifecycleManager;
import org.briarproject.api.privategroup.GroupMessageHeader;
import org.briarproject.api.privategroup.PrivateGroup; import org.briarproject.api.privategroup.PrivateGroup;
import org.briarproject.api.privategroup.PrivateGroupManager; import org.briarproject.api.privategroup.PrivateGroupManager;
import org.briarproject.api.sync.ClientId; import org.briarproject.api.sync.ClientId;
@@ -29,6 +31,7 @@ import java.util.logging.Logger;
import javax.inject.Inject; import javax.inject.Inject;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
public class GroupListControllerImpl extends DbControllerImpl public class GroupListControllerImpl extends DbControllerImpl
@@ -81,59 +84,77 @@ public class GroupListControllerImpl extends DbControllerImpl
@CallSuper @CallSuper
public void eventOccurred(Event e) { public void eventOccurred(Event e) {
if (e instanceof GroupMessageAddedEvent) { if (e instanceof GroupMessageAddedEvent) {
final GroupMessageAddedEvent m = (GroupMessageAddedEvent) e; GroupMessageAddedEvent g = (GroupMessageAddedEvent) e;
LOG.info("New group message added"); LOG.info("Private group message added");
listener.runOnUiThreadUnlessDestroyed(new Runnable() { onGroupMessageAdded(g.getHeader());
@Override
public void run() {
listener.onGroupMessageAdded(m.getHeader());
}
});
} else if (e instanceof GroupAddedEvent) { } else if (e instanceof GroupAddedEvent) {
final GroupAddedEvent gae = (GroupAddedEvent) e; GroupAddedEvent g = (GroupAddedEvent) e;
ClientId id = gae.getGroup().getClientId(); ClientId id = g.getGroup().getClientId();
if (id.equals(groupManager.getClientId())) { if (id.equals(groupManager.getClientId())) {
LOG.info("Private group added"); LOG.info("Private group added");
listener.runOnUiThreadUnlessDestroyed(new Runnable() { onGroupAdded(g.getGroup().getId());
@Override
public void run() {
listener.onGroupAdded(gae.getGroup().getId());
}
});
} }
} else if (e instanceof GroupRemovedEvent) { } else if (e instanceof GroupRemovedEvent) {
final GroupRemovedEvent gre = (GroupRemovedEvent) e; GroupRemovedEvent g = (GroupRemovedEvent) e;
ClientId id = gre.getGroup().getClientId(); ClientId id = g.getGroup().getClientId();
if (id.equals(groupManager.getClientId())) { if (id.equals(groupManager.getClientId())) {
LOG.info("Private group removed"); LOG.info("Private group removed");
listener.runOnUiThreadUnlessDestroyed(new Runnable() { onGroupRemoved(g.getGroup().getId());
@Override
public void run() {
listener.onGroupRemoved(gre.getGroup().getId());
}
});
} }
} }
} }
private void onGroupMessageAdded(final GroupMessageHeader h) {
listener.runOnUiThreadUnlessDestroyed(new Runnable() {
@Override
public void run() {
listener.onGroupMessageAdded(h);
}
});
}
private void onGroupAdded(final GroupId g) {
listener.runOnUiThreadUnlessDestroyed(new Runnable() {
@Override
public void run() {
listener.onGroupAdded(g);
}
});
}
private void onGroupRemoved(final GroupId g) {
listener.runOnUiThreadUnlessDestroyed(new Runnable() {
@Override
public void run() {
listener.onGroupRemoved(g);
}
});
}
@Override @Override
public void loadGroups( public void loadGroups(
final ResultExceptionHandler<Collection<GroupItem>, DbException> handler) { final ResultExceptionHandler<Collection<GroupItem>, DbException> handler) {
runOnDbThread(new Runnable() { runOnDbThread(new Runnable() {
@Override @Override
public void run() { public void run() {
LOG.info("Loading groups from database...");
try { try {
long now = System.currentTimeMillis();
Collection<PrivateGroup> groups = Collection<PrivateGroup> groups =
groupManager.getPrivateGroups(); groupManager.getPrivateGroups();
List<GroupItem> items = new ArrayList<>(groups.size()); List<GroupItem> items = new ArrayList<>(groups.size());
for (PrivateGroup g : groups) { for (PrivateGroup g : groups) {
GroupCount c = groupManager.getGroupCount(g.getId()); try {
boolean dissolved = groupManager.isDissolved(g.getId()); GroupId id = g.getId();
items.add(new GroupItem(g, c.getMsgCount(), GroupCount count = groupManager.getGroupCount(id);
c.getLatestMsgTime(), c.getUnreadCount(), boolean dissolved = groupManager.isDissolved(id);
dissolved)); items.add(new GroupItem(g, count, dissolved));
} catch (NoSuchGroupException e) {
// Continue
}
} }
long duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO))
LOG.info("Loading groups took " + duration + " ms");
handler.onResult(items); handler.onResult(items);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) if (LOG.isLoggable(WARNING))
@@ -150,9 +171,13 @@ public class GroupListControllerImpl extends DbControllerImpl
runOnDbThread(new Runnable() { runOnDbThread(new Runnable() {
@Override @Override
public void run() { public void run() {
LOG.info("Removing group from database...");
try { try {
long now = System.currentTimeMillis();
groupManager.removePrivateGroup(g); groupManager.removePrivateGroup(g);
long duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO))
LOG.info("Removing group took " + duration + " ms");
handler.onResult(null);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e); LOG.log(WARNING, e.toString(), e);

View File

@@ -1,6 +1,5 @@
package org.briarproject.android.privategroup.list; package org.briarproject.android.privategroup.list;
import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.annotation.UiThread; import android.support.annotation.UiThread;
@@ -16,7 +15,6 @@ 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.fragment.BaseFragment; import org.briarproject.android.fragment.BaseFragment;
import org.briarproject.android.invitation.AddContactActivity;
import org.briarproject.android.privategroup.list.GroupListController.GroupListListener; import org.briarproject.android.privategroup.list.GroupListController.GroupListListener;
import org.briarproject.android.privategroup.list.GroupViewHolder.OnGroupRemoveClickListener; import org.briarproject.android.privategroup.list.GroupViewHolder.OnGroupRemoveClickListener;
import org.briarproject.android.view.BriarRecyclerView; import org.briarproject.android.view.BriarRecyclerView;
@@ -152,12 +150,9 @@ public class GroupListFragment extends BaseFragment implements
new UiResultExceptionHandler<Collection<GroupItem>, DbException>( new UiResultExceptionHandler<Collection<GroupItem>, DbException>(
listener) { listener) {
@Override @Override
public void onResultUi(Collection<GroupItem> result) { public void onResultUi(Collection<GroupItem> groups) {
if (result.isEmpty()) { if (groups.isEmpty()) list.showData();
list.showData(); else adapter.addAll(groups);
} else {
adapter.addAll(result);
}
} }
@Override @Override

View File

@@ -88,7 +88,7 @@ class GroupViewHolder extends RecyclerView.ViewHolder {
postCount.setTextColor( postCount.setTextColor(
getColor(ctx, R.color.briar_text_secondary)); getColor(ctx, R.color.briar_text_secondary));
long lastUpdate = group.getLastUpdate(); long lastUpdate = group.getTimestamp();
date.setText(AndroidUtils.formatDate(ctx, lastUpdate)); date.setText(AndroidUtils.formatDate(ctx, lastUpdate));
date.setVisibility(VISIBLE); date.setVisibility(VISIBLE);
avatar.setProblem(false); avatar.setProblem(false);

View File

@@ -163,8 +163,8 @@ public class DevReportActivity extends BaseCrashReportDialog
} }
@Override @Override
public void onResume() { public void onStart() {
super.onResume(); super.onStart();
if (chevron.isSelected()) refresh(); if (chevron.isSelected()) refresh();
} }

View File

@@ -30,7 +30,6 @@ import org.briarproject.api.sync.GroupId;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.logging.Logger; import java.util.logging.Logger;
@@ -57,11 +56,11 @@ public class ContactSelectorFragment extends BaseFragment implements
// Fields that are accessed from background threads must be volatile // Fields that are accessed from background threads must be volatile
@Inject @Inject
protected volatile ContactManager contactManager; volatile ContactManager contactManager;
@Inject @Inject
protected volatile IdentityManager identityManager; volatile IdentityManager identityManager;
@Inject @Inject
protected volatile ForumSharingManager forumSharingManager; volatile ForumSharingManager forumSharingManager;
private volatile GroupId groupId; private volatile GroupId groupId;
@@ -91,8 +90,9 @@ public class ContactSelectorFragment extends BaseFragment implements
setHasOptionsMenu(true); setHasOptionsMenu(true);
Bundle args = getArguments(); Bundle args = getArguments();
groupId = new GroupId(args.getByteArray(GROUP_ID)); byte[] b = args.getByteArray(GROUP_ID);
if (groupId == null) throw new IllegalStateException("No GroupId"); if (b == null) throw new IllegalStateException("No GroupId");
groupId = new GroupId(b);
} }
@Override @Override
@@ -125,12 +125,16 @@ public class ContactSelectorFragment extends BaseFragment implements
} }
@Override @Override
public void onResume() { public void onStart() {
super.onResume(); super.onStart();
loadContacts(selectedContacts);
}
if (selectedContacts != null) @Override
loadContacts(Collections.unmodifiableCollection(selectedContacts)); public void onStop() {
else loadContacts(null); super.onStop();
adapter.clear();
list.showProgressBar();
} }
@Override @Override
@@ -202,9 +206,8 @@ public class ContactSelectorFragment extends BaseFragment implements
long duration = System.currentTimeMillis() - now; long duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO)) if (LOG.isLoggable(INFO))
LOG.info("Load took " + duration + " ms"); LOG.info("Load took " + duration + " ms");
displayContacts(Collections.unmodifiableList(contacts)); displayContacts(contacts);
} catch (DbException e) { } catch (DbException e) {
displayContacts(Collections.<ContactListItem>emptyList());
if (LOG.isLoggable(WARNING)) if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e); LOG.log(WARNING, e.toString(), e);
} }
@@ -216,8 +219,8 @@ public class ContactSelectorFragment extends BaseFragment implements
shareActivity.runOnUiThreadUnlessDestroyed(new Runnable() { shareActivity.runOnUiThreadUnlessDestroyed(new Runnable() {
@Override @Override
public void run() { public void run() {
if (!contacts.isEmpty()) adapter.addAll(contacts); if (contacts.isEmpty()) list.showData();
else list.showData(); else adapter.addAll(contacts);
updateMenuItem(); updateMenuItem();
} }
}); });

View File

@@ -2,6 +2,7 @@ package org.briarproject.android.sharing;
import android.content.Context; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.CallSuper;
import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.LinearLayoutManager;
import android.widget.Toast; import android.widget.Toast;
@@ -42,7 +43,6 @@ abstract class InvitationsActivity extends BriarActivity
adapter = getAdapter(this, this); adapter = getAdapter(this, this);
list = (BriarRecyclerView) findViewById(R.id.list); list = (BriarRecyclerView) findViewById(R.id.list);
if (list != null) { if (list != null) {
list.setLayoutManager(new LinearLayoutManager(this)); list.setLayoutManager(new LinearLayoutManager(this));
@@ -51,21 +51,22 @@ abstract class InvitationsActivity extends BriarActivity
} }
@Override @Override
public void onResume() { public void onStart() {
super.onResume(); super.onStart();
eventBus.addListener(this); eventBus.addListener(this);
loadInvitations(false); loadInvitations(false);
} }
@Override @Override
public void onPause() { public void onStop() {
super.onPause(); super.onStop();
eventBus.removeListener(this); eventBus.removeListener(this);
adapter.clear(); adapter.clear();
list.showProgressBar(); list.showProgressBar();
} }
@Override @Override
@CallSuper
public void eventOccurred(Event e) { public void eventOccurred(Event e) {
if (e instanceof ContactRemovedEvent) { if (e instanceof ContactRemovedEvent) {
LOG.info("Contact removed, reloading..."); LOG.info("Contact removed, reloading...");
@@ -110,8 +111,8 @@ abstract class InvitationsActivity extends BriarActivity
LOG.info("No more invitations available, finishing"); LOG.info("No more invitations available, finishing");
finish(); finish();
} else { } else {
if (clear) adapter.clear(); if (clear) adapter.setItems(invitations);
adapter.addAll(invitations); else adapter.addAll(invitations);
} }
} }
}); });

View File

@@ -29,9 +29,9 @@ public class InvitationsBlogActivity extends InvitationsActivity {
// Fields that are accessed from background threads must be volatile // Fields that are accessed from background threads must be volatile
@Inject @Inject
protected volatile BlogManager blogManager; volatile BlogManager blogManager;
@Inject @Inject
protected volatile BlogSharingManager blogSharingManager; volatile BlogSharingManager blogSharingManager;
@Override @Override
public void injectActivity(ActivityComponent component) { public void injectActivity(ActivityComponent component) {
@@ -62,31 +62,34 @@ public class InvitationsBlogActivity extends InvitationsActivity {
} }
} }
@Override
protected InvitationAdapter getAdapter(Context ctx, protected InvitationAdapter getAdapter(Context ctx,
AvailableForumClickListener listener) { AvailableForumClickListener listener) {
return new BlogInvitationAdapter(ctx, listener); return new BlogInvitationAdapter(ctx, listener);
} }
@Override
protected void loadInvitations(final boolean clear) { protected void loadInvitations(final boolean clear) {
runOnDbThread(new Runnable() { runOnDbThread(new Runnable() {
@Override @Override
public void run() { public void run() {
Collection<InvitationItem> invitations = new ArrayList<>();
try { try {
Collection<InvitationItem> invitations = new ArrayList<>();
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
invitations.addAll(blogSharingManager.getInvitations()); invitations.addAll(blogSharingManager.getInvitations());
long duration = System.currentTimeMillis() - now; long duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO)) if (LOG.isLoggable(INFO))
LOG.info("Load took " + duration + " ms"); LOG.info("Load took " + duration + " ms");
displayInvitations(invitations, clear);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e); LOG.log(WARNING, e.toString(), e);
} }
displayInvitations(invitations, clear);
} }
}); });
} }
@Override
protected void respondToInvitation(final InvitationItem item, protected void respondToInvitation(final InvitationItem item,
final boolean accept) { final boolean accept) {
runOnDbThread(new Runnable() { runOnDbThread(new Runnable() {
@@ -95,6 +98,7 @@ public class InvitationsBlogActivity extends InvitationsActivity {
try { try {
Blog b = (Blog) item.getShareable(); Blog b = (Blog) item.getShareable();
for (Contact c : item.getNewSharers()) { for (Contact c : item.getNewSharers()) {
// TODO: What happens if a contact has been removed?
blogSharingManager.respondToInvitation(b, c, accept); blogSharingManager.respondToInvitation(b, c, accept);
} }
} catch (DbException e) { } catch (DbException e) {
@@ -105,10 +109,12 @@ public class InvitationsBlogActivity extends InvitationsActivity {
}); });
} }
@Override
protected int getAcceptRes() { protected int getAcceptRes() {
return R.string.blogs_sharing_joined_toast; return R.string.blogs_sharing_joined_toast;
} }
@Override
protected int getDeclineRes() { protected int getDeclineRes() {
return R.string.blogs_sharing_declined_toast; return R.string.blogs_sharing_declined_toast;
} }

View File

@@ -29,9 +29,9 @@ public class InvitationsForumActivity extends InvitationsActivity {
// Fields that are accessed from background threads must be volatile // Fields that are accessed from background threads must be volatile
@Inject @Inject
protected volatile ForumManager forumManager; volatile ForumManager forumManager;
@Inject @Inject
protected volatile ForumSharingManager forumSharingManager; volatile ForumSharingManager forumSharingManager;
@Override @Override
public void injectActivity(ActivityComponent component) { public void injectActivity(ActivityComponent component) {
@@ -62,31 +62,34 @@ public class InvitationsForumActivity extends InvitationsActivity {
} }
} }
@Override
protected InvitationAdapter getAdapter(Context ctx, protected InvitationAdapter getAdapter(Context ctx,
AvailableForumClickListener listener) { AvailableForumClickListener listener) {
return new ForumInvitationAdapter(ctx, listener); return new ForumInvitationAdapter(ctx, listener);
} }
@Override
protected void loadInvitations(final boolean clear) { protected void loadInvitations(final boolean clear) {
runOnDbThread(new Runnable() { runOnDbThread(new Runnable() {
@Override @Override
public void run() { public void run() {
Collection<InvitationItem> invitations = new ArrayList<>();
try { try {
Collection<InvitationItem> invitations = new ArrayList<>();
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
invitations.addAll(forumSharingManager.getInvitations()); invitations.addAll(forumSharingManager.getInvitations());
long duration = System.currentTimeMillis() - now; long duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO)) if (LOG.isLoggable(INFO))
LOG.info("Load took " + duration + " ms"); LOG.info("Load took " + duration + " ms");
displayInvitations(invitations, clear);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e); LOG.log(WARNING, e.toString(), e);
} }
displayInvitations(invitations, clear);
} }
}); });
} }
@Override
protected void respondToInvitation(final InvitationItem item, protected void respondToInvitation(final InvitationItem item,
final boolean accept) { final boolean accept) {
runOnDbThread(new Runnable() { runOnDbThread(new Runnable() {
@@ -95,6 +98,7 @@ public class InvitationsForumActivity extends InvitationsActivity {
try { try {
Forum f = (Forum) item.getShareable(); Forum f = (Forum) item.getShareable();
for (Contact c : item.getNewSharers()) { for (Contact c : item.getNewSharers()) {
// TODO: What happens if a contact has been removed?
forumSharingManager.respondToInvitation(f, c, accept); forumSharingManager.respondToInvitation(f, c, accept);
} }
} catch (DbException e) { } catch (DbException e) {
@@ -105,10 +109,12 @@ public class InvitationsForumActivity extends InvitationsActivity {
}); });
} }
@Override
protected int getAcceptRes() { protected int getAcceptRes() {
return R.string.forum_joined_toast; return R.string.forum_joined_toast;
} }
@Override
protected int getDeclineRes() { protected int getDeclineRes() {
return R.string.forum_declined_toast; return R.string.forum_declined_toast;
} }

View File

@@ -63,13 +63,21 @@ abstract class SharingStatusActivity extends BriarActivity {
} }
@Override @Override
public void onResume() { public void onStart() {
super.onResume(); super.onStart();
loadSharedBy(); loadSharedBy();
loadSharedWith(); loadSharedWith();
} }
@Override
public void onStop() {
super.onStop();
sharedByAdapter.clear();
sharedByList.showProgressBar();
sharedWithAdapter.clear();
sharedWithList.showProgressBar();
}
@Override @Override
public boolean onOptionsItemSelected(final MenuItem item) { public boolean onOptionsItemSelected(final MenuItem item) {
// Handle presses on the action bar items // Handle presses on the action bar items
@@ -97,11 +105,11 @@ abstract class SharingStatusActivity extends BriarActivity {
} }
private void loadSharedBy() { private void loadSharedBy() {
dbController.runOnDbThread(new Runnable() { runOnDbThread(new Runnable() {
@Override @Override
public void run() { public void run() {
List<ContactListItem> contactItems = new ArrayList<>();
try { try {
List<ContactListItem> contactItems = new ArrayList<>();
for (Contact c : getSharedBy()) { for (Contact c : getSharedBy()) {
LocalAuthor localAuthor = identityManager LocalAuthor localAuthor = identityManager
.getLocalAuthor(c.getLocalAuthorId()); .getLocalAuthor(c.getLocalAuthorId());
@@ -110,11 +118,11 @@ abstract class SharingStatusActivity extends BriarActivity {
groupId, new GroupCount(0, 0, 0)); groupId, new GroupCount(0, 0, 0));
contactItems.add(item); contactItems.add(item);
} }
displaySharedBy(contactItems);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e); LOG.log(WARNING, e.toString(), e);
} }
displaySharedBy(contactItems);
} }
}); });
} }
@@ -123,21 +131,18 @@ abstract class SharingStatusActivity extends BriarActivity {
runOnUiThreadUnlessDestroyed(new Runnable() { runOnUiThreadUnlessDestroyed(new Runnable() {
@Override @Override
public void run() { public void run() {
if (contacts.isEmpty()) { if (contacts.isEmpty()) sharedByList.showData();
sharedByList.showData(); else sharedByAdapter.addAll(contacts);
} else {
sharedByAdapter.addAll(contacts);
}
} }
}); });
} }
private void loadSharedWith() { private void loadSharedWith() {
dbController.runOnDbThread(new Runnable() { runOnDbThread(new Runnable() {
@Override @Override
public void run() { public void run() {
List<ContactListItem> contactItems = new ArrayList<>();
try { try {
List<ContactListItem> contactItems = new ArrayList<>();
for (Contact c : getSharedWith()) { for (Contact c : getSharedWith()) {
LocalAuthor localAuthor = identityManager LocalAuthor localAuthor = identityManager
.getLocalAuthor(c.getLocalAuthorId()); .getLocalAuthor(c.getLocalAuthorId());
@@ -146,11 +151,11 @@ abstract class SharingStatusActivity extends BriarActivity {
groupId, new GroupCount(0, 0, 0)); groupId, new GroupCount(0, 0, 0));
contactItems.add(item); contactItems.add(item);
} }
displaySharedWith(contactItems);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e); LOG.log(WARNING, e.toString(), e);
} }
displaySharedWith(contactItems);
} }
}); });
} }
@@ -159,11 +164,8 @@ abstract class SharingStatusActivity extends BriarActivity {
runOnUiThreadUnlessDestroyed(new Runnable() { runOnUiThreadUnlessDestroyed(new Runnable() {
@Override @Override
public void run() { public void run() {
if (contacts.isEmpty()) { if (contacts.isEmpty()) sharedWithList.showData();
sharedWithList.showData(); else sharedWithAdapter.addAll(contacts);
} else {
sharedWithAdapter.addAll(contacts);
}
} }
}); });
} }

View File

@@ -75,7 +75,7 @@ public abstract class ThreadListActivity<G extends NamedGroup, I extends ThreadI
if (state != null) { if (state != null) {
byte[] replyIdBytes = state.getByteArray(KEY_REPLY_ID); byte[] replyIdBytes = state.getByteArray(KEY_REPLY_ID);
if(replyIdBytes != null) replyId = new MessageId(replyIdBytes); if (replyIdBytes != null) replyId = new MessageId(replyIdBytes);
} }
loadItems(); loadItems();
@@ -131,35 +131,33 @@ public abstract class ThreadListActivity<G extends NamedGroup, I extends ThreadI
@CallSuper @CallSuper
@Override @Override
public void onResume() { public void onStart() {
super.onResume(); super.onStart();
list.startPeriodicUpdate(); list.startPeriodicUpdate();
} }
@CallSuper @CallSuper
@Override @Override
public void onPause() { public void onStop() {
super.onPause(); super.onStop();
list.stopPeriodicUpdate(); list.stopPeriodicUpdate();
} }
@Override @Override
protected void onRestoreInstanceState(Bundle savedInstanceState) { protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState); super.onRestoreInstanceState(savedInstanceState);
textInput.setVisibility( boolean visible = savedInstanceState.getBoolean(KEY_INPUT_VISIBILITY);
savedInstanceState.getBoolean(KEY_INPUT_VISIBILITY) ? textInput.setVisibility(visible ? VISIBLE : GONE);
VISIBLE : GONE);
} }
@Override @Override
protected void onSaveInstanceState(Bundle outState) { protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState); super.onSaveInstanceState(outState);
outState.putBoolean(KEY_INPUT_VISIBILITY, boolean visible = textInput.getVisibility() == VISIBLE;
textInput.getVisibility() == VISIBLE); outState.putBoolean(KEY_INPUT_VISIBILITY, visible);
ThreadItem replyItem = adapter.getReplyItem(); ThreadItem replyItem = adapter.getReplyItem();
if (replyItem != null) { if (replyItem != null) {
outState.putByteArray(KEY_REPLY_ID, outState.putByteArray(KEY_REPLY_ID, replyItem.getId().getBytes());
replyItem.getId().getBytes());
} }
} }

View File

@@ -49,8 +49,7 @@ public abstract class ThreadListControllerImpl<G extends NamedGroup, I extends T
private final EventBus eventBus; private final EventBus eventBus;
private final Clock clock; private final Clock clock;
private final Map<MessageId, String> bodyCache = private final Map<MessageId, String> bodyCache = new ConcurrentHashMap<>();
new ConcurrentHashMap<>();
private volatile GroupId groupId; private volatile GroupId groupId;
@@ -82,14 +81,14 @@ public abstract class ThreadListControllerImpl<G extends NamedGroup, I extends T
@CallSuper @CallSuper
@Override @Override
public void onActivityResume() { public void onActivityStart() {
notificationManager.blockNotification(getGroupId()); notificationManager.blockNotification(getGroupId());
eventBus.addListener(this); eventBus.addListener(this);
} }
@CallSuper @CallSuper
@Override @Override
public void onActivityPause() { public void onActivityStop() {
notificationManager.unblockNotification(getGroupId()); notificationManager.unblockNotification(getGroupId());
eventBus.removeListener(this); eventBus.removeListener(this);
} }
@@ -127,8 +126,7 @@ public abstract class ThreadListControllerImpl<G extends NamedGroup, I extends T
G groupItem = loadNamedGroup(); G groupItem = loadNamedGroup();
long duration = System.currentTimeMillis() - now; long duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO)) if (LOG.isLoggable(INFO))
LOG.info( LOG.info("Loading group took " + duration + " ms");
"Loading named group took " + duration + " ms");
handler.onResult(groupItem); handler.onResult(groupItem);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) if (LOG.isLoggable(WARNING))
@@ -149,7 +147,6 @@ public abstract class ThreadListControllerImpl<G extends NamedGroup, I extends T
runOnDbThread(new Runnable() { runOnDbThread(new Runnable() {
@Override @Override
public void run() { public void run() {
LOG.info("Loading items...");
try { try {
// Load headers // Load headers
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
@@ -193,8 +190,8 @@ public abstract class ThreadListControllerImpl<G extends NamedGroup, I extends T
runOnDbThread(new Runnable() { runOnDbThread(new Runnable() {
@Override @Override
public void run() { public void run() {
LOG.info("Loading item...");
try { try {
long now = System.currentTimeMillis();
String body; String body;
if (!bodyCache.containsKey(header.getId())) { if (!bodyCache.containsKey(header.getId())) {
body = loadMessageBody(header.getId()); body = loadMessageBody(header.getId());
@@ -202,6 +199,9 @@ public abstract class ThreadListControllerImpl<G extends NamedGroup, I extends T
} else { } else {
body = bodyCache.get(header.getId()); body = bodyCache.get(header.getId());
} }
long duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO))
LOG.info("Loading item took " + duration + " ms");
I item = buildItem(header, body); I item = buildItem(header, body);
handler.onResult(item); handler.onResult(item);
} catch (DbException e) { } catch (DbException e) {
@@ -250,12 +250,16 @@ public abstract class ThreadListControllerImpl<G extends NamedGroup, I extends T
@Override @Override
public void run() { public void run() {
try { try {
long now = System.currentTimeMillis();
LocalAuthor author = identityManager.getLocalAuthor(); LocalAuthor author = identityManager.getLocalAuthor();
long timestamp = getLatestTimestamp(); long timestamp = getLatestTimestamp();
timestamp = timestamp = Math.max(timestamp, clock.currentTimeMillis());
Math.max(timestamp, clock.currentTimeMillis()); long duration = System.currentTimeMillis() - now;
createMessage(body, timestamp, parentId, author, if (LOG.isLoggable(INFO)) {
handler); LOG.info("Loading identity and timestamp took " +
duration + " ms");
}
createMessage(body, timestamp, parentId, author, handler);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e); LOG.log(WARNING, e.toString(), e);
@@ -274,8 +278,11 @@ public abstract class ThreadListControllerImpl<G extends NamedGroup, I extends T
cryptoExecutor.execute(new Runnable() { cryptoExecutor.execute(new Runnable() {
@Override @Override
public void run() { public void run() {
LOG.info("Creating message..."); long now = System.currentTimeMillis();
M msg = createLocalMessage(body, timestamp, parentId, author); M msg = createLocalMessage(body, timestamp, parentId, author);
long duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO))
LOG.info("Creating message took " + duration + " ms");
storePost(msg, body, handler); storePost(msg, body, handler);
} }
}); });
@@ -291,7 +298,6 @@ public abstract class ThreadListControllerImpl<G extends NamedGroup, I extends T
@Override @Override
public void run() { public void run() {
try { try {
LOG.info("Store message...");
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
H header = addLocalMessage(msg); H header = addLocalMessage(msg);
bodyCache.put(msg.getMessage().getId(), body); bodyCache.put(msg.getMessage().getId(), body);
@@ -354,10 +360,7 @@ public abstract class ThreadListControllerImpl<G extends NamedGroup, I extends T
} }
private void checkGroupId() { private void checkGroupId() {
if (groupId == null) { if (groupId == null) throw new IllegalStateException();
throw new IllegalStateException(
"You must set the GroupId before the controller is started.");
}
} }
} }

View File

@@ -75,6 +75,13 @@ public abstract class BriarAdapter<T, V extends ViewHolder>
this.items.addAll(items); this.items.addAll(items);
} }
public void setItems(Collection<T> items) {
this.items.beginBatchedUpdates();
this.items.clear();
this.items.addAll(items);
this.items.endBatchedUpdates();
}
@Nullable @Nullable
public T getItemAt(int position) { public T getItemAt(int position) {
if (position == INVALID_POSITION || position >= items.size()) { if (position == INVALID_POSITION || position >= items.size()) {

View File

@@ -1,17 +1,25 @@
package org.briarproject.api.crypto; package org.briarproject.api.crypto;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import javax.inject.Qualifier; import javax.inject.Qualifier;
/** Annotation for injecting the executor for long-running crypto tasks. */ import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Annotation for injecting the executor for long-running crypto tasks. Also
* used for annotating methods that should run on the crypto executor.
* <p>
* The contract of this executor is that tasks may be run concurrently, and
* submitting a task will never block. Tasks must not run indefinitely. Tasks
* submitted during shutdown are discarded.
*/
@Qualifier @Qualifier
@Target({FIELD, METHOD, PARAMETER}) @Target({FIELD, METHOD, PARAMETER})
@Retention(RUNTIME) @Retention(RUNTIME)
public @interface CryptoExecutor {} public @interface CryptoExecutor {
}

View File

@@ -1,21 +1,23 @@
package org.briarproject.api.db; package org.briarproject.api.db;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import javax.inject.Qualifier; import javax.inject.Qualifier;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/** /**
* Annotation for injecting the executor for database tasks. * Annotation for injecting the executor for database tasks. Also used for
* annotating methods that should run on the database executor.
* <p> * <p>
* The contract of this executor is that tasks are executed in the order * The contract of this executor is that tasks are run in the order they're
* they're submitted, tasks are not executed concurrently, and submitting a * submitted, tasks are not run concurrently, and submitting a task will never
* task will never block. * block. Tasks must not run indefinitely. Tasks submitted during shutdown are
* discarded.
*/ */
@Qualifier @Qualifier
@Target({ FIELD, METHOD, PARAMETER }) @Target({ FIELD, METHOD, PARAMETER })

View File

@@ -1,5 +1,6 @@
package org.briarproject.api.event; package org.briarproject.api.event;
import org.briarproject.api.contact.ContactId;
import org.briarproject.api.messaging.PrivateMessageHeader; import org.briarproject.api.messaging.PrivateMessageHeader;
import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.GroupId;
@@ -9,11 +10,13 @@ import org.briarproject.api.sync.GroupId;
public class PrivateMessageReceivedEvent extends Event { public class PrivateMessageReceivedEvent extends Event {
private final PrivateMessageHeader messageHeader; private final PrivateMessageHeader messageHeader;
private final ContactId contactId;
private final GroupId groupId; private final GroupId groupId;
public PrivateMessageReceivedEvent(PrivateMessageHeader messageHeader, public PrivateMessageReceivedEvent(PrivateMessageHeader messageHeader,
GroupId groupId) { ContactId contactId, GroupId groupId) {
this.messageHeader = messageHeader; this.messageHeader = messageHeader;
this.contactId = contactId;
this.groupId = groupId; this.groupId = groupId;
} }
@@ -21,6 +24,10 @@ public class PrivateMessageReceivedEvent extends Event {
return messageHeader; return messageHeader;
} }
public ContactId getContactId() {
return contactId;
}
public GroupId getGroupId() { public GroupId getGroupId() {
return groupId; return groupId;
} }

View File

@@ -1,17 +1,25 @@
package org.briarproject.api.lifecycle; package org.briarproject.api.lifecycle;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import javax.inject.Qualifier; import javax.inject.Qualifier;
/** Annotation for injecting the executor used by long-lived IO tasks. */ import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Annotation for injecting the executor for long-running IO tasks. Also used
* for annotating methods that should run on the UI executor.
* <p>
* The contract of this executor is that tasks may be run concurrently, and
* submitting a task will never block. Tasks may run indefinitely. Tasks
* submitted during shutdown are discarded.
*/
@Qualifier @Qualifier
@Target({ FIELD, METHOD, PARAMETER }) @Target({FIELD, METHOD, PARAMETER})
@Retention(RUNTIME) @Retention(RUNTIME)
public @interface IoExecutor {} public @interface IoExecutor {
}

View File

@@ -102,10 +102,11 @@ class MessagingManagerImpl extends ConversationClientImpl
boolean local = meta.getBoolean("local"); boolean local = meta.getBoolean("local");
boolean read = meta.getBoolean(MSG_KEY_READ); boolean read = meta.getBoolean(MSG_KEY_READ);
PrivateMessageHeader header = new PrivateMessageHeader( PrivateMessageHeader header = new PrivateMessageHeader(
m.getId(), m.getGroupId(), timestamp, contentType, local, read, m.getId(), groupId, timestamp, contentType, local, read,
false, false); false, false);
ContactId contactId = getContactId(txn, groupId);
PrivateMessageReceivedEvent event = new PrivateMessageReceivedEvent( PrivateMessageReceivedEvent event = new PrivateMessageReceivedEvent(
header, groupId); header, contactId, groupId);
txn.attach(event); txn.attach(event);
trackIncomingMessage(txn, m); trackIncomingMessage(txn, m);
@@ -133,6 +134,17 @@ class MessagingManagerImpl extends ConversationClientImpl
} }
} }
private ContactId getContactId(Transaction txn, GroupId g)
throws DbException {
try {
BdfDictionary meta =
clientHelper.getGroupMetadataAsDictionary(txn, g);
return new ContactId(meta.getLong("contactId").intValue());
} catch (FormatException e) {
throw new DbException(e);
}
}
@Override @Override
public ContactId getContactId(GroupId g) throws DbException { public ContactId getContactId(GroupId g) throws DbException {
try { try {