From 044719432a0ca2d0e06fa621eca846de7476d14b Mon Sep 17 00:00:00 2001 From: Ernir Erlingsson Date: Fri, 21 Apr 2017 13:52:53 +0200 Subject: [PATCH 1/5] list position save and restore now implemented for threaded lists --- .../briar/android/AndroidComponent.java | 3 ++ .../android/threaded/ThreadItemAdapter.java | 27 ++++++++++++++ .../android/threaded/ThreadItemList.java | 15 ++++++++ .../android/threaded/ThreadItemListImpl.java | 22 ++++++++++++ .../android/threaded/ThreadListActivity.java | 22 ++++++++++-- .../threaded/ThreadListController.java | 9 ++++- .../threaded/ThreadListControllerImpl.java | 36 ++++++++++++++++--- .../android/forum/ForumActivityTest.java | 15 ++++---- .../briar/api/client/MessageTracker.java | 15 ++++++++ .../briar/client/MessageTrackerConstants.java | 1 + .../briar/client/MessageTrackerImpl.java | 26 ++++++++++++++ .../briar/forum/ForumManagerTest.java | 18 ++++++++++ 12 files changed, 193 insertions(+), 16 deletions(-) create mode 100644 briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemList.java create mode 100644 briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemListImpl.java diff --git a/briar-android/src/main/java/org/briarproject/briar/android/AndroidComponent.java b/briar-android/src/main/java/org/briarproject/briar/android/AndroidComponent.java index 992304364..9394f9d02 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/AndroidComponent.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/AndroidComponent.java @@ -32,6 +32,7 @@ import org.briarproject.briar.api.android.ScreenFilterMonitor; import org.briarproject.briar.api.blog.BlogManager; import org.briarproject.briar.api.blog.BlogPostFactory; import org.briarproject.briar.api.blog.BlogSharingManager; +import org.briarproject.briar.api.client.MessageTracker; import org.briarproject.briar.api.feed.FeedManager; import org.briarproject.briar.api.forum.ForumManager; import org.briarproject.briar.api.forum.ForumSharingManager; @@ -78,6 +79,8 @@ public interface AndroidComponent @DatabaseExecutor Executor databaseExecutor(); + MessageTracker messageTracker(); + LifecycleManager lifecycleManager(); IdentityManager identityManager(); diff --git a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemAdapter.java b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemAdapter.java index 72b03a03f..9e4bbe51e 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemAdapter.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemAdapter.java @@ -1,5 +1,6 @@ package org.briarproject.briar.android.threaded; +import android.os.Handler; import android.support.annotation.Nullable; import android.support.annotation.UiThread; import android.support.v7.widget.LinearLayoutManager; @@ -26,6 +27,7 @@ public class ThreadItemAdapter protected final NestedTreeList items = new NestedTreeList<>(); private final ThreadItemListener listener; private final LinearLayoutManager layoutManager; + private final Handler handler = new Handler(); private volatile int revision = 0; @@ -64,6 +66,31 @@ public class ThreadItemAdapter revision++; } + void setBottomItem(MessageId messageId) { + if (messageId != null) { + int pos = 0; + for (I item : items) { + if (item.getId().equals(messageId)) { + scrollToPosition(pos); + break; + + } + pos++; + } + } + } + + private void scrollToPosition(final int pos) { + // Post call ensures that the list scrolls AFTER it has been propagated + // and the layout has been calculated. + handler.post(new Runnable() { + @Override + public void run() { + layoutManager.scrollToPosition(pos); + } + }); + } + public void setItems(Collection items) { this.items.clear(); this.items.addAll(items); diff --git a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemList.java b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemList.java new file mode 100644 index 000000000..53d6ed633 --- /dev/null +++ b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemList.java @@ -0,0 +1,15 @@ +package org.briarproject.briar.android.threaded; + +import org.briarproject.bramble.api.sync.MessageId; + +import java.util.List; + +import javax.annotation.Nullable; + +public interface ThreadItemList extends List { + + @Nullable + MessageId getBottomVisibleItemId(); + + void setBottomVisibleItemId(@Nullable MessageId bottomVisibleItemId); +} diff --git a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemListImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemListImpl.java new file mode 100644 index 000000000..880d29739 --- /dev/null +++ b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemListImpl.java @@ -0,0 +1,22 @@ +package org.briarproject.briar.android.threaded; + +import org.briarproject.bramble.api.sync.MessageId; + +import java.util.ArrayList; + +import javax.annotation.Nullable; + +public class ThreadItemListImpl extends ArrayList + implements ThreadItemList { + + private MessageId bottomVisibleItemId; + + @Override + public MessageId getBottomVisibleItemId() { + return bottomVisibleItemId; + } + + public void setBottomVisibleItemId(@Nullable MessageId bottomVisibleItemId) { + this.bottomVisibleItemId = bottomVisibleItemId; + } +} diff --git a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListActivity.java index 8106be7ed..dc184365e 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListActivity.java @@ -26,6 +26,7 @@ import org.briarproject.briar.android.controller.SharingController; import org.briarproject.briar.android.controller.SharingController.SharingListener; import org.briarproject.briar.android.controller.handler.UiResultExceptionHandler; import org.briarproject.briar.android.threaded.ThreadItemAdapter.ThreadItemListener; +import org.briarproject.briar.android.threaded.ThreadListController.ThreadListDataSource; import org.briarproject.briar.android.threaded.ThreadListController.ThreadListListener; import org.briarproject.briar.android.view.BriarRecyclerView; import org.briarproject.briar.android.view.TextInputView; @@ -51,7 +52,7 @@ import static org.briarproject.briar.android.threaded.ThreadItemAdapter.UnreadCo public abstract class ThreadListActivity, I extends ThreadItem, H extends PostHeader> extends BriarActivity implements ThreadListListener, TextInputListener, SharingListener, - ThreadItemListener { + ThreadItemListener, ThreadListDataSource { protected static final String KEY_REPLY_ID = "replyId"; @@ -68,6 +69,7 @@ public abstract class ThreadListActivity getController(); + @Inject protected SharingController sharingController; @@ -104,6 +106,7 @@ public abstract class ThreadListActivity, DbException>(this) { + new UiResultExceptionHandler, DbException>( + this) { @Override - public void onResultUi(Collection items) { + public void onResultUi(ThreadItemList items) { if (revision == adapter.getRevision()) { adapter.incrementRevision(); if (items.isEmpty()) { list.showData(); } else { adapter.setItems(items); + adapter.setBottomItem( + items.getBottomVisibleItemId()); list.showData(); updateTextInput(replyId); } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListController.java b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListController.java index caebd1ec6..a062c8322 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListController.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListController.java @@ -6,6 +6,7 @@ import org.briarproject.bramble.api.contact.ContactId; import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.sync.GroupId; +import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.briar.android.DestroyableContext; import org.briarproject.briar.android.controller.ActivityLifecycleController; import org.briarproject.briar.android.controller.handler.ExceptionHandler; @@ -30,7 +31,7 @@ public interface ThreadListController handler); - void loadItems(ResultExceptionHandler, DbException> handler); + void loadItems(ResultExceptionHandler, DbException> handler); void markItemRead(I item); @@ -52,4 +53,10 @@ public interface ThreadListController, DbException> handler) { + final ResultExceptionHandler, DbException> handler) { checkGroupId(); runOnDbThread(new Runnable() { @Override @@ -293,11 +311,19 @@ public abstract class ThreadListControllerImpl buildItems(Collection headers) { - List items = new ArrayList<>(); + private ThreadItemList buildItems(Collection headers) { + ThreadItemList items = new ThreadItemListImpl<>(); for (H h : headers) { items.add(buildItem(h, bodyCache.get(h.getId()))); } + try { + MessageId msgId = messageTracker.loadStoredMessageId(groupId); + if (LOG.isLoggable(INFO)) + LOG.info("Loaded last top visible message id " + msgId); + items.setBottomVisibleItemId(msgId); + } catch (DbException e) { + e.printStackTrace(); + } return items; } diff --git a/briar-android/src/test/java/org/briarproject/briar/android/forum/ForumActivityTest.java b/briar-android/src/test/java/org/briarproject/briar/android/forum/ForumActivityTest.java index 8a3461c2e..96ffc88eb 100644 --- a/briar-android/src/test/java/org/briarproject/briar/android/forum/ForumActivityTest.java +++ b/briar-android/src/test/java/org/briarproject/briar/android/forum/ForumActivityTest.java @@ -13,6 +13,8 @@ import org.briarproject.briar.BuildConfig; import org.briarproject.briar.android.TestBriarApplication; import org.briarproject.briar.android.controller.handler.UiResultExceptionHandler; import org.briarproject.briar.android.threaded.ThreadItemAdapter; +import org.briarproject.briar.android.threaded.ThreadItemList; +import org.briarproject.briar.android.threaded.ThreadItemListImpl; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -23,10 +25,7 @@ import org.robolectric.Robolectric; import org.robolectric.RobolectricGradleTestRunner; import org.robolectric.annotation.Config; -import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; -import java.util.List; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertTrue; @@ -81,7 +80,7 @@ public class ForumActivityTest { private TestForumActivity forumActivity; @Captor - private ArgumentCaptor, DbException>> + private ArgumentCaptor, DbException>> rc; @Before @@ -93,7 +92,7 @@ public class ForumActivityTest { .withIntent(intent).create().resume().get(); } - private List getDummyData() { + private ThreadItemList getDummyData() { ForumItem[] forumItems = new ForumItem[6]; for (int i = 0; i < forumItems.length; i++) { AuthorId authorId = new AuthorId(TestUtils.getRandomId()); @@ -103,13 +102,15 @@ public class ForumActivityTest { AUTHORS[i], System.currentTimeMillis(), author, UNKNOWN); forumItems[i].setLevel(LEVELS[i]); } - return new ArrayList<>(Arrays.asList(forumItems)); + ThreadItemList list = new ThreadItemListImpl<>(); + list.addAll(Arrays.asList(forumItems)); + return list; } @Test public void testNestedEntries() { ForumController mc = forumActivity.getController(); - List dummyData = getDummyData(); + ThreadItemList dummyData = getDummyData(); verify(mc, times(1)).loadItems(rc.capture()); rc.getValue().onResult(dummyData); ThreadItemAdapter adapter = forumActivity.getAdapter(); diff --git a/briar-api/src/main/java/org/briarproject/briar/api/client/MessageTracker.java b/briar-api/src/main/java/org/briarproject/briar/api/client/MessageTracker.java index 44c26fef4..5d6418f0a 100644 --- a/briar-api/src/main/java/org/briarproject/briar/api/client/MessageTracker.java +++ b/briar-api/src/main/java/org/briarproject/briar/api/client/MessageTracker.java @@ -7,6 +7,8 @@ import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.Message; import org.briarproject.bramble.api.sync.MessageId; +import javax.annotation.Nullable; + @NotNullByDefault public interface MessageTracker { @@ -38,6 +40,19 @@ public interface MessageTracker { void trackMessage(Transaction txn, GroupId g, long timestamp, boolean read) throws DbException; + /** + * Loads the stored message id for the respective group id or returns null + * if none is available. + */ + @Nullable + MessageId loadStoredMessageId(GroupId g) throws DbException; + + /** + * Stores the message id for the respective group id. Exactly one message id + * can be stored for any group id at any time, older values are overwritten. + */ + void storeMessageId(GroupId g, MessageId m) throws DbException; + /** * Marks a message as read or unread and updates the group count. */ diff --git a/briar-core/src/main/java/org/briarproject/briar/client/MessageTrackerConstants.java b/briar-core/src/main/java/org/briarproject/briar/client/MessageTrackerConstants.java index ca689fc1c..81a1d603b 100644 --- a/briar-core/src/main/java/org/briarproject/briar/client/MessageTrackerConstants.java +++ b/briar-core/src/main/java/org/briarproject/briar/client/MessageTrackerConstants.java @@ -2,6 +2,7 @@ package org.briarproject.briar.client; public interface MessageTrackerConstants { + String GROUP_KEY_STORED_MESSAGE_ID = "storedMessageId"; String GROUP_KEY_MSG_COUNT = "messageCount"; String GROUP_KEY_UNREAD_COUNT = "unreadCount"; String GROUP_KEY_LATEST_MSG = "latestMessageTime"; diff --git a/briar-core/src/main/java/org/briarproject/briar/client/MessageTrackerImpl.java b/briar-core/src/main/java/org/briarproject/briar/client/MessageTrackerImpl.java index bd230dca8..716b1308e 100644 --- a/briar-core/src/main/java/org/briarproject/briar/client/MessageTrackerImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/client/MessageTrackerImpl.java @@ -13,11 +13,13 @@ import org.briarproject.bramble.api.sync.Message; import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.briar.api.client.MessageTracker; +import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; import javax.inject.Inject; import static org.briarproject.briar.client.MessageTrackerConstants.GROUP_KEY_LATEST_MSG; import static org.briarproject.briar.client.MessageTrackerConstants.GROUP_KEY_MSG_COUNT; +import static org.briarproject.briar.client.MessageTrackerConstants.GROUP_KEY_STORED_MESSAGE_ID; import static org.briarproject.briar.client.MessageTrackerConstants.GROUP_KEY_UNREAD_COUNT; import static org.briarproject.briar.client.MessageTrackerConstants.MSG_KEY_READ; @@ -57,6 +59,30 @@ class MessageTrackerImpl implements MessageTracker { latestMsgTime)); } + @Nullable + @Override + public MessageId loadStoredMessageId(GroupId g) throws DbException { + try { + BdfDictionary d = clientHelper.getGroupMetadataAsDictionary(g); + byte[] msgBytes = d.getOptionalRaw(GROUP_KEY_STORED_MESSAGE_ID); + return msgBytes != null? new MessageId(msgBytes) : null; + } catch (FormatException e) { + throw new DbException(e); + } + } + + @Override + public void storeMessageId(GroupId g, MessageId m) throws DbException { + BdfDictionary d = BdfDictionary.of( + new BdfEntry(GROUP_KEY_STORED_MESSAGE_ID, m) + ); + try { + clientHelper.mergeGroupMetadata(g, d); + } catch (FormatException e) { + throw new DbException(e); + } + } + @Override public GroupCount getGroupCount(GroupId g) throws DbException { GroupCount count; diff --git a/briar-core/src/test/java/org/briarproject/briar/forum/ForumManagerTest.java b/briar-core/src/test/java/org/briarproject/briar/forum/ForumManagerTest.java index 30567fdf2..09805ce44 100644 --- a/briar-core/src/test/java/org/briarproject/briar/forum/ForumManagerTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/forum/ForumManagerTest.java @@ -1,7 +1,10 @@ package org.briarproject.briar.forum; +import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.sync.GroupId; +import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.test.TestDatabaseModule; +import org.briarproject.bramble.test.TestUtils; import org.briarproject.briar.api.forum.Forum; import org.briarproject.briar.api.forum.ForumManager; import org.briarproject.briar.api.forum.ForumPost; @@ -10,6 +13,7 @@ import org.briarproject.briar.api.forum.ForumSharingManager; import org.briarproject.briar.test.BriarIntegrationTest; import org.briarproject.briar.test.BriarIntegrationTestComponent; import org.briarproject.briar.test.DaggerBriarIntegrationTestComponent; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -223,4 +227,18 @@ public class ForumManagerTest assertEquals(1, forumManager1.getPostHeaders(g1).size()); } + @Test + public void testMessageStoreAndLoad() { + MessageId msgId = new MessageId(TestUtils.getRandomId()); + MessageId loadedId = null; + try { + messageTracker0.storeMessageId(groupId0, msgId); + loadedId = messageTracker0.loadStoredMessageId(groupId0); + } catch (DbException e) { + e.printStackTrace(); + } + Assert.assertNotNull(loadedId); + Assert.assertTrue(msgId.equals(loadedId)); + } + } From 5f4e1ecdfd7da00a723de0b8f4de706fa63fe8e1 Mon Sep 17 00:00:00 2001 From: Ernir Erlingsson Date: Mon, 24 Apr 2017 23:34:34 +0200 Subject: [PATCH 2/5] improvements after code review #1 fix --- .../android/threaded/ThreadItemAdapter.java | 26 +++++++++---------- .../android/threaded/ThreadListActivity.java | 5 ++-- .../threaded/ThreadListController.java | 6 ++--- .../threaded/ThreadListControllerImpl.java | 13 +++------- .../briar/client/MessageTrackerImpl.java | 2 +- 5 files changed, 22 insertions(+), 30 deletions(-) diff --git a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemAdapter.java b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemAdapter.java index 9e4bbe51e..0a36ac80e 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemAdapter.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemAdapter.java @@ -66,31 +66,29 @@ public class ThreadItemAdapter revision++; } - void setBottomItem(MessageId messageId) { + // Useful when the adapter has not calculated the dimension yet + void postSetItemWithIdVisible(@Nullable final MessageId messageId) { + new Handler().post(new Runnable() { + @Override + public void run() { + setItemWithIdVisible(messageId); + } + }); + } + + void setItemWithIdVisible(@Nullable MessageId messageId) { if (messageId != null) { int pos = 0; for (I item : items) { if (item.getId().equals(messageId)) { - scrollToPosition(pos); + layoutManager.scrollToPosition(pos); break; - } pos++; } } } - private void scrollToPosition(final int pos) { - // Post call ensures that the list scrolls AFTER it has been propagated - // and the layout has been calculated. - handler.post(new Runnable() { - @Override - public void run() { - layoutManager.scrollToPosition(pos); - } - }); - } - public void setItems(Collection items) { this.items.clear(); this.items.addAll(items); diff --git a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListActivity.java index dc184365e..68cec97a2 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListActivity.java @@ -148,7 +148,8 @@ public abstract class ThreadListActivity handler); - interface ThreadListListener extends DestroyableContext { + interface ThreadListListener extends ThreadListDataSource { @UiThread void onHeaderReceived(H header); @@ -53,10 +53,10 @@ public interface ThreadListController Date: Fri, 5 May 2017 11:22:21 +0200 Subject: [PATCH 3/5] fixed unread buttons for threaded lists and akwizgran's comments --- .../android/controller/DbControllerImpl.java | 2 +- .../android/forum/ForumControllerImpl.java | 5 +- .../conversation/GroupControllerImpl.java | 6 +- .../android/threaded/ThreadItemAdapter.java | 16 +----- .../android/threaded/ThreadItemList.java | 2 +- .../android/threaded/ThreadItemListImpl.java | 2 +- .../android/threaded/ThreadListActivity.java | 21 ++++--- .../threaded/ThreadListController.java | 2 +- .../threaded/ThreadListControllerImpl.java | 45 ++++++++------- .../android/view/UnreadMessageButton.java | 11 +--- .../briar/client/MessageTrackerTest.java | 57 +++++++++++++++++++ .../briar/forum/ForumManagerTest.java | 18 ------ 12 files changed, 111 insertions(+), 76 deletions(-) create mode 100644 briar-core/src/test/java/org/briarproject/briar/client/MessageTrackerTest.java diff --git a/briar-android/src/main/java/org/briarproject/briar/android/controller/DbControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/controller/DbControllerImpl.java index eaeb7a06e..6ae01b8a5 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/controller/DbControllerImpl.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/controller/DbControllerImpl.java @@ -17,7 +17,7 @@ public class DbControllerImpl implements DbController { private static final Logger LOG = Logger.getLogger(DbControllerImpl.class.getName()); - private final Executor dbExecutor; + protected final Executor dbExecutor; private final LifecycleManager lifecycleManager; @Inject diff --git a/briar-android/src/main/java/org/briarproject/briar/android/forum/ForumControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/forum/ForumControllerImpl.java index 4c52f6154..8d97e7810 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/forum/ForumControllerImpl.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/forum/ForumControllerImpl.java @@ -17,6 +17,7 @@ import org.briarproject.briar.android.controller.handler.ResultExceptionHandler; import org.briarproject.briar.android.forum.ForumController.ForumListener; import org.briarproject.briar.android.threaded.ThreadListControllerImpl; import org.briarproject.briar.api.android.AndroidNotificationManager; +import org.briarproject.briar.api.client.MessageTracker; import org.briarproject.briar.api.client.MessageTracker.GroupCount; import org.briarproject.briar.api.forum.Forum; import org.briarproject.briar.api.forum.ForumInvitationResponse; @@ -55,10 +56,10 @@ class ForumControllerImpl extends LifecycleManager lifecycleManager, IdentityManager identityManager, @CryptoExecutor Executor cryptoExecutor, ForumManager forumManager, ForumSharingManager forumSharingManager, - EventBus eventBus, Clock clock, + EventBus eventBus, Clock clock, MessageTracker messageTracker, AndroidNotificationManager notificationManager) { super(dbExecutor, lifecycleManager, identityManager, cryptoExecutor, - eventBus, clock, notificationManager); + eventBus, clock, notificationManager, messageTracker); this.forumManager = forumManager; this.forumSharingManager = forumSharingManager; } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupControllerImpl.java index 0c7530559..db6029e57 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupControllerImpl.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupControllerImpl.java @@ -17,6 +17,7 @@ import org.briarproject.briar.android.controller.handler.ResultExceptionHandler; import org.briarproject.briar.android.privategroup.conversation.GroupController.GroupListener; import org.briarproject.briar.android.threaded.ThreadListControllerImpl; import org.briarproject.briar.api.android.AndroidNotificationManager; +import org.briarproject.briar.api.client.MessageTracker; import org.briarproject.briar.api.client.MessageTracker.GroupCount; import org.briarproject.briar.api.privategroup.GroupMember; import org.briarproject.briar.api.privategroup.GroupMessage; @@ -60,9 +61,10 @@ class GroupControllerImpl extends @CryptoExecutor Executor cryptoExecutor, PrivateGroupManager privateGroupManager, GroupMessageFactory groupMessageFactory, EventBus eventBus, - Clock clock, AndroidNotificationManager notificationManager) { + MessageTracker messageTracker, Clock clock, + AndroidNotificationManager notificationManager) { super(dbExecutor, lifecycleManager, identityManager, cryptoExecutor, - eventBus, clock, notificationManager); + eventBus, clock, notificationManager, messageTracker); this.privateGroupManager = privateGroupManager; this.groupMessageFactory = groupMessageFactory; } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemAdapter.java b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemAdapter.java index 0a36ac80e..99a4a3335 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemAdapter.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemAdapter.java @@ -66,17 +66,7 @@ public class ThreadItemAdapter revision++; } - // Useful when the adapter has not calculated the dimension yet - void postSetItemWithIdVisible(@Nullable final MessageId messageId) { - new Handler().post(new Runnable() { - @Override - public void run() { - setItemWithIdVisible(messageId); - } - }); - } - - void setItemWithIdVisible(@Nullable MessageId messageId) { + void setItemWithIdVisible(MessageId messageId) { if (messageId != null) { int pos = 0; for (I item : items) { @@ -169,7 +159,7 @@ public class ThreadItemAdapter /** * Returns the position of the first unread item below the current viewport */ - public int getVisibleUnreadPosBottom() { + int getVisibleUnreadPosBottom() { final int positionBottom = layoutManager.findLastVisibleItemPosition(); if (positionBottom == NO_POSITION) return NO_POSITION; for (int i = positionBottom + 1; i < items.size(); i++) { @@ -181,7 +171,7 @@ public class ThreadItemAdapter /** * Returns the position of the first unread item above the current viewport */ - public int getVisibleUnreadPosTop() { + int getVisibleUnreadPosTop() { final int positionTop = layoutManager.findFirstVisibleItemPosition(); int position = NO_POSITION; for (int i = 0; i < items.size(); i++) { diff --git a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemList.java b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemList.java index 53d6ed633..d4f067c2f 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemList.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemList.java @@ -9,7 +9,7 @@ import javax.annotation.Nullable; public interface ThreadItemList extends List { @Nullable - MessageId getBottomVisibleItemId(); + MessageId getFirstVisibleItemId(); void setBottomVisibleItemId(@Nullable MessageId bottomVisibleItemId); } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemListImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemListImpl.java index 880d29739..f6fb80e68 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemListImpl.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemListImpl.java @@ -12,7 +12,7 @@ public class ThreadItemListImpl extends ArrayList private MessageId bottomVisibleItemId; @Override - public MessageId getBottomVisibleItemId() { + public MessageId getFirstVisibleItemId() { return bottomVisibleItemId; } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListActivity.java index 68cec97a2..b62f35c77 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListActivity.java @@ -149,11 +149,12 @@ public abstract class ThreadListActivity items) { + adapter.setItems(items); + MessageId messageId = items.getFirstVisibleItemId(); + if (messageId != null) + adapter.setItemWithIdVisible(messageId); + updateUnreadCount(); + list.showData(); + } + protected void loadSharingContacts() { getController().loadSharingContacts( new UiResultExceptionHandler, DbException>( diff --git a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListController.java b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListController.java index 45aa69a0a..d39c8b453 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListController.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListController.java @@ -56,7 +56,7 @@ public interface ThreadListController buildItems(Collection headers) { + private ThreadItemList buildItems(Collection headers) + throws DbException { ThreadItemList items = new ThreadItemListImpl<>(); for (H h : headers) { items.add(buildItem(h, bodyCache.get(h.getId()))); } - try { - MessageId msgId = messageTracker.loadStoredMessageId(groupId); - if (LOG.isLoggable(INFO)) - LOG.info("Loaded last top visible message id " + msgId); - items.setBottomVisibleItemId(msgId); - } catch (DbException e) { - e.printStackTrace(); - } + MessageId msgId = messageTracker.loadStoredMessageId(groupId); + if (LOG.isLoggable(INFO)) + LOG.info("Loaded last top visible message id " + msgId); + items.setBottomVisibleItemId(msgId); return items; } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/view/UnreadMessageButton.java b/briar-android/src/main/java/org/briarproject/briar/android/view/UnreadMessageButton.java index e7f4fa92f..4a5360043 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/view/UnreadMessageButton.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/view/UnreadMessageButton.java @@ -36,8 +36,7 @@ public class UnreadMessageButton extends FrameLayout { LayoutInflater inflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); - inflater - .inflate(R.layout.unread_message_button, this, true); + inflater.inflate(R.layout.unread_message_button, this, true); fab = (FloatingActionButton) findViewById(R.id.fab); unread = (TextView) findViewById(R.id.unreadCountView); @@ -64,15 +63,11 @@ public class UnreadMessageButton extends FrameLayout { public void setUnreadCount(int count) { if (count == 0) { - fab.setVisibility(GONE); -// fab.hide(); - unread.setVisibility(GONE); + setVisibility(INVISIBLE); } else { // FIXME: Use animations when upgrading to support library 24.2.0 // https://code.google.com/p/android/issues/detail?id=216469 - fab.setVisibility(VISIBLE); -// if (!fab.isShown()) fab.show(); - unread.setVisibility(VISIBLE); + setVisibility(VISIBLE); unread.setText(String.valueOf(count)); } } diff --git a/briar-core/src/test/java/org/briarproject/briar/client/MessageTrackerTest.java b/briar-core/src/test/java/org/briarproject/briar/client/MessageTrackerTest.java new file mode 100644 index 000000000..6f841703f --- /dev/null +++ b/briar-core/src/test/java/org/briarproject/briar/client/MessageTrackerTest.java @@ -0,0 +1,57 @@ +package org.briarproject.briar.client; + +import org.briarproject.bramble.api.client.ClientHelper; +import org.briarproject.bramble.api.data.BdfDictionary; +import org.briarproject.bramble.api.data.BdfEntry; +import org.briarproject.bramble.api.db.DatabaseComponent; +import org.briarproject.bramble.api.sync.GroupId; +import org.briarproject.bramble.api.sync.MessageId; +import org.briarproject.bramble.test.TestUtils; +import org.briarproject.briar.api.client.MessageTracker; +import org.briarproject.briar.test.BriarTestCase; +import org.jmock.Expectations; +import org.jmock.Mockery; +import org.junit.After; +import org.junit.Assert; +import org.junit.Test; + +import static org.briarproject.briar.client.MessageTrackerConstants.GROUP_KEY_STORED_MESSAGE_ID; + +public class MessageTrackerTest extends BriarTestCase { + + protected final Mockery context = new Mockery(); + protected final GroupId groupId = new GroupId(TestUtils.getRandomId()); + protected final ClientHelper clientHelper = + context.mock(ClientHelper.class); + private final DatabaseComponent db = context.mock(DatabaseComponent.class); + private final MessageId messageId = new MessageId(TestUtils.getRandomId()); + private final MessageTracker messageTracker = + new MessageTrackerImpl(db, clientHelper); + private final BdfDictionary dictionary = BdfDictionary.of( + new BdfEntry(GROUP_KEY_STORED_MESSAGE_ID, messageId) + ); + + @Test + public void testMessageStore() throws Exception { + context.checking(new Expectations() {{ + oneOf(clientHelper).mergeGroupMetadata(groupId, dictionary); + }}); + messageTracker.storeMessageId(groupId, messageId); + } + + @Test + public void testMessageLoad() throws Exception { + context.checking(new Expectations() {{ + oneOf(clientHelper).getGroupMetadataAsDictionary(groupId); + will(returnValue(dictionary)); + }}); + MessageId loadedId = messageTracker.loadStoredMessageId(groupId); + Assert.assertNotNull(loadedId); + Assert.assertTrue(messageId.equals(loadedId)); + } + + @After + public void checkExpectations() { + context.assertIsSatisfied(); + } +} diff --git a/briar-core/src/test/java/org/briarproject/briar/forum/ForumManagerTest.java b/briar-core/src/test/java/org/briarproject/briar/forum/ForumManagerTest.java index 09805ce44..30567fdf2 100644 --- a/briar-core/src/test/java/org/briarproject/briar/forum/ForumManagerTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/forum/ForumManagerTest.java @@ -1,10 +1,7 @@ package org.briarproject.briar.forum; -import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.sync.GroupId; -import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.test.TestDatabaseModule; -import org.briarproject.bramble.test.TestUtils; import org.briarproject.briar.api.forum.Forum; import org.briarproject.briar.api.forum.ForumManager; import org.briarproject.briar.api.forum.ForumPost; @@ -13,7 +10,6 @@ import org.briarproject.briar.api.forum.ForumSharingManager; import org.briarproject.briar.test.BriarIntegrationTest; import org.briarproject.briar.test.BriarIntegrationTestComponent; import org.briarproject.briar.test.DaggerBriarIntegrationTestComponent; -import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -227,18 +223,4 @@ public class ForumManagerTest assertEquals(1, forumManager1.getPostHeaders(g1).size()); } - @Test - public void testMessageStoreAndLoad() { - MessageId msgId = new MessageId(TestUtils.getRandomId()); - MessageId loadedId = null; - try { - messageTracker0.storeMessageId(groupId0, msgId); - loadedId = messageTracker0.loadStoredMessageId(groupId0); - } catch (DbException e) { - e.printStackTrace(); - } - Assert.assertNotNull(loadedId); - Assert.assertTrue(msgId.equals(loadedId)); - } - } From 7024e04d15bf5573135a4726908184f1256b7cce Mon Sep 17 00:00:00 2001 From: Ernir Erlingsson Date: Sat, 6 May 2017 21:31:53 +0200 Subject: [PATCH 4/5] fixed final akwizgran comments --- .../briar/android/threaded/ThreadItemAdapter.java | 14 ++++++-------- .../briar/android/threaded/ThreadListActivity.java | 2 +- .../briar/client/MessageTrackerTest.java | 11 ++--------- 3 files changed, 9 insertions(+), 18 deletions(-) diff --git a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemAdapter.java b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemAdapter.java index 99a4a3335..1c10a8b36 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemAdapter.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemAdapter.java @@ -67,15 +67,13 @@ public class ThreadItemAdapter } void setItemWithIdVisible(MessageId messageId) { - if (messageId != null) { - int pos = 0; - for (I item : items) { - if (item.getId().equals(messageId)) { - layoutManager.scrollToPosition(pos); - break; - } - pos++; + int pos = 0; + for (I item : items) { + if (item.getId().equals(messageId)) { + layoutManager.scrollToPosition(pos); + break; } + pos++; } } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListActivity.java index b62f35c77..fba82cc14 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListActivity.java @@ -154,7 +154,7 @@ public abstract class ThreadListActivity Date: Sat, 6 May 2017 21:36:25 +0200 Subject: [PATCH 5/5] final pre-merge fixes --- .../org/briarproject/briar/android/threaded/ThreadItemList.java | 2 +- .../briarproject/briar/android/threaded/ThreadItemListImpl.java | 2 +- .../briar/android/threaded/ThreadListControllerImpl.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemList.java b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemList.java index d4f067c2f..f517e8e9c 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemList.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemList.java @@ -11,5 +11,5 @@ public interface ThreadItemList extends List { @Nullable MessageId getFirstVisibleItemId(); - void setBottomVisibleItemId(@Nullable MessageId bottomVisibleItemId); + void setFirstVisibleId(@Nullable MessageId bottomVisibleItemId); } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemListImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemListImpl.java index f6fb80e68..2886607ed 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemListImpl.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemListImpl.java @@ -16,7 +16,7 @@ public class ThreadItemListImpl extends ArrayList return bottomVisibleItemId; } - public void setBottomVisibleItemId(@Nullable MessageId bottomVisibleItemId) { + public void setFirstVisibleId(@Nullable MessageId bottomVisibleItemId) { this.bottomVisibleItemId = bottomVisibleItemId; } } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListControllerImpl.java index add7a9776..0793d785a 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListControllerImpl.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListControllerImpl.java @@ -317,7 +317,7 @@ public abstract class ThreadListControllerImpl