diff --git a/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationActivity.java index a25460cd4..2766501a8 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationActivity.java @@ -47,7 +47,6 @@ import org.briarproject.bramble.api.plugin.ConnectionRegistry; import org.briarproject.bramble.api.plugin.event.ContactConnectedEvent; import org.briarproject.bramble.api.plugin.event.ContactDisconnectedEvent; import org.briarproject.bramble.api.settings.SettingsManager; -import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.api.sync.event.MessagesAckedEvent; import org.briarproject.bramble.api.sync.event.MessagesSentEvent; @@ -256,6 +255,9 @@ public class ConversationActivity extends BriarActivity list.setLayoutManager(layoutManager); list.setAdapter(adapter); list.setEmptyText(getString(R.string.no_private_messages)); + ConversationScrollListener scrollListener = + new ConversationScrollListener(adapter, viewModel); + list.getRecyclerView().addOnScrollListener(scrollListener); textInputView = findViewById(R.id.text_input_container); if (FEATURE_FLAG_IMAGE_ATTACHMENTS) { @@ -787,23 +789,6 @@ public class ConversationActivity extends BriarActivity .show(); } - @Override - public void onItemVisible(ConversationItem item) { - if (!item.isRead()) markMessageRead(item.getGroupId(), item.getId()); - } - - private void markMessageRead(GroupId g, MessageId m) { - runOnDbThread(() -> { - try { - long start = now(); - messagingManager.setReadFlag(g, m, true); - logDuration(LOG, "Marking read", start); - } catch (DbException e) { - logException(LOG, WARNING, e); - } - }); - } - @UiThread @Override public void respondToRequest(ConversationRequestItem item, boolean accept) { diff --git a/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationAdapter.java b/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationAdapter.java index 0194a2d7f..b9fa34812 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationAdapter.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationAdapter.java @@ -14,12 +14,14 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.briar.R; import org.briarproject.briar.android.util.BriarAdapter; +import org.briarproject.briar.android.util.ItemReturningAdapter; import javax.annotation.Nullable; @NotNullByDefault class ConversationAdapter - extends BriarAdapter { + extends BriarAdapter + implements ItemReturningAdapter { private ConversationListener listener; private final RecycledViewPool imageViewPool; @@ -69,7 +71,6 @@ class ConversationAdapter public void onBindViewHolder(ConversationItemViewHolder ui, int position) { ConversationItem item = items.get(position); ui.bind(item); - listener.onItemVisible(item); } @Override diff --git a/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationItem.java b/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationItem.java index 5ab0ee33c..5fb4c5b4b 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationItem.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationItem.java @@ -69,6 +69,10 @@ abstract class ConversationItem { return read; } + void markRead() { + read = true; + } + /** * Only useful for outgoing messages. */ diff --git a/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationListener.java b/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationListener.java index 9c8db9538..d7c445fae 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationListener.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationListener.java @@ -9,8 +9,6 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault; @NotNullByDefault interface ConversationListener { - void onItemVisible(ConversationItem item); - void respondToRequest(ConversationRequestItem item, boolean accept); void openRequestedShareable(ConversationRequestItem item); diff --git a/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationScrollListener.java b/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationScrollListener.java new file mode 100644 index 000000000..da90aa0cf --- /dev/null +++ b/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationScrollListener.java @@ -0,0 +1,26 @@ +package org.briarproject.briar.android.conversation; + +import org.briarproject.bramble.api.nullsafety.NotNullByDefault; +import org.briarproject.briar.android.view.BriarRecyclerViewScrollListener; + +@NotNullByDefault +class ConversationScrollListener extends + BriarRecyclerViewScrollListener { + + private final ConversationViewModel viewModel; + + protected ConversationScrollListener(ConversationAdapter adapter, + ConversationViewModel viewModel) { + super(adapter); + this.viewModel = viewModel; + } + + @Override + protected void onItemVisible(ConversationItem item) { + if (!item.isRead()) { + viewModel.markMessageRead(item.getGroupId(), item.getId()); + item.markRead(); + } + } + +} diff --git a/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationViewModel.java b/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationViewModel.java index 5f93fcd14..c9b3a1cd7 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationViewModel.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationViewModel.java @@ -26,6 +26,7 @@ import org.briarproject.bramble.api.settings.Settings; import org.briarproject.bramble.api.settings.SettingsManager; import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.Message; +import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.briar.android.util.UiUtils; import org.briarproject.briar.api.messaging.Attachment; import org.briarproject.briar.api.messaging.AttachmentHeader; @@ -150,6 +151,18 @@ public class ConversationViewModel extends AndroidViewModel { }); } + void markMessageRead(GroupId g, MessageId m) { + dbExecutor.execute(() -> { + try { + long start = now(); + messagingManager.setReadFlag(g, m, true); + logDuration(LOG, "Marking read", start); + } catch (DbException e) { + logException(LOG, WARNING, e); + } + }); + } + void setContactAlias(String alias) { dbExecutor.execute(() -> { try { diff --git a/briar-android/src/main/java/org/briarproject/briar/android/threaded/BaseThreadItemViewHolder.java b/briar-android/src/main/java/org/briarproject/briar/android/threaded/BaseThreadItemViewHolder.java index 529fa7d00..a0f54bad3 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/threaded/BaseThreadItemViewHolder.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/threaded/BaseThreadItemViewHolder.java @@ -51,7 +51,6 @@ public abstract class BaseThreadItemViewHolder } else if (!item.isRead()) { layout.setActivated(true); animateFadeOut(); - listener.onUnreadItemVisible(item); } else { layout.setActivated(false); } 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 15bd410e6..c9af77016 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 @@ -10,6 +10,7 @@ import android.view.ViewGroup; import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.briar.R; +import org.briarproject.briar.android.util.ItemReturningAdapter; import org.briarproject.briar.android.util.VersionedAdapter; import java.util.Collection; @@ -21,7 +22,7 @@ import static android.support.v7.widget.RecyclerView.NO_POSITION; @UiThread public class ThreadItemAdapter extends RecyclerView.Adapter> - implements VersionedAdapter { + implements VersionedAdapter, ItemReturningAdapter { static final int UNDEFINED = -1; @@ -136,30 +137,6 @@ public class ThreadItemAdapter return null; } - /** - * Gets the number of unread items above and below the current view port. - * - * Attention: Do not call this when the list is still scrolling, - * because then the view port is unknown. - */ - public UnreadCount getUnreadCount() { - int positionTop = layoutManager.findFirstVisibleItemPosition(); - int positionBottom = layoutManager.findLastVisibleItemPosition(); - if (positionTop == NO_POSITION && positionBottom == NO_POSITION) - return new UnreadCount(0, 0); - - int unreadCounterTop = 0, unreadCounterBottom = 0; - for (int i = 0; i < items.size(); i++) { - I item = items.get(i); - if (i < positionTop && !item.isRead()) { - unreadCounterTop++; - } else if (i > positionBottom && !item.isRead()) { - unreadCounterBottom++; - } - } - return new UnreadCount(unreadCounterTop, unreadCounterBottom); - } - /** * Returns the position of the first unread item below the current viewport */ @@ -188,20 +165,7 @@ public class ThreadItemAdapter return NO_POSITION; } - static class UnreadCount { - - final int top, bottom; - - private UnreadCount(int top, int bottom) { - this.top = top; - this.bottom = bottom; - } - } - public interface ThreadItemListener { - - void onUnreadItemVisible(I item); - void onReplyClick(I item); } 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 ed0ac5b94..c679ce2ad 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 @@ -9,7 +9,6 @@ import android.support.annotation.UiThread; import android.support.design.widget.Snackbar; import android.support.v7.app.ActionBar; import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; import android.view.MenuItem; import org.briarproject.bramble.api.contact.ContactId; @@ -43,10 +42,7 @@ import javax.inject.Inject; import static android.support.design.widget.Snackbar.make; import static android.support.v7.widget.RecyclerView.NO_POSITION; -import static android.support.v7.widget.RecyclerView.SCROLL_STATE_IDLE; -import static java.util.logging.Level.INFO; import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty; -import static org.briarproject.briar.android.threaded.ThreadItemAdapter.UnreadCount; @MethodsNotNullByDefault @ParametersNotNullByDefault @@ -61,11 +57,11 @@ public abstract class ThreadListActivity scrollListener; protected BriarRecyclerView list; private LinearLayoutManager layoutManager; protected TextInputView textInput; protected GroupId groupId; - private UnreadMessageButton upButton, downButton; @Nullable private MessageId replyId; @@ -76,7 +72,6 @@ public abstract class ThreadListActivity(adapter, getController(), + upButton, downButton); + list.getRecyclerView().addOnScrollListener(scrollListener); - list.getRecyclerView().addOnScrollListener( - new RecyclerView.OnScrollListener() { - @Override - public void onScrolled(RecyclerView recyclerView, int dx, - int dy) { - super.onScrolled(recyclerView, dx, dy); - if (dx == 0 && dy == 0) { - // scrollToPosition has been called and finished - updateUnreadCount(); - } - } - - @Override - public void onScrollStateChanged(RecyclerView recyclerView, - int newState) { - super.onScrollStateChanged(recyclerView, newState); - if (newState == SCROLL_STATE_IDLE) { - updateUnreadCount(); - } - } - }); - upButton = findViewById(R.id.upButton); - downButton = findViewById(R.id.downButton); upButton.setOnClickListener(v -> { int position = adapter.getVisibleUnreadPosTop(); if (position != NO_POSITION) { @@ -211,7 +187,6 @@ public abstract class ThreadListActivity