mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-17 05:09:53 +01:00
Submit thread list items to ListAdapter
This commit is contained in:
@@ -19,7 +19,6 @@ import org.briarproject.briar.android.threaded.ThreadItemAdapter;
|
|||||||
import org.briarproject.briar.android.threaded.ThreadListActivity;
|
import org.briarproject.briar.android.threaded.ThreadListActivity;
|
||||||
import org.briarproject.briar.android.threaded.ThreadListController;
|
import org.briarproject.briar.android.threaded.ThreadListController;
|
||||||
import org.briarproject.briar.android.threaded.ThreadListViewModel;
|
import org.briarproject.briar.android.threaded.ThreadListViewModel;
|
||||||
import org.briarproject.briar.api.forum.Forum;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
@@ -37,7 +36,7 @@ import static org.briarproject.briar.api.forum.ForumConstants.MAX_FORUM_POST_TEX
|
|||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
public class ForumActivity extends
|
public class ForumActivity extends
|
||||||
ThreadListActivity<Forum, ForumPostItem, ThreadItemAdapter<ForumPostItem>>
|
ThreadListActivity<ForumPostItem, ThreadItemAdapter<ForumPostItem>>
|
||||||
implements ForumListener {
|
implements ForumListener {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@@ -55,12 +54,12 @@ public class ForumActivity extends
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ThreadListController<Forum, ForumPostItem> getController() {
|
protected ThreadListController<ForumPostItem> getController() {
|
||||||
return forumController;
|
return forumController;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ThreadListViewModel<Forum, ForumPostItem> getViewModel() {
|
protected ThreadListViewModel<ForumPostItem> getViewModel() {
|
||||||
return viewModel;
|
return viewModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,12 +3,11 @@ package org.briarproject.briar.android.forum;
|
|||||||
import org.briarproject.bramble.api.contact.ContactId;
|
import org.briarproject.bramble.api.contact.ContactId;
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
import org.briarproject.briar.android.threaded.ThreadListController;
|
import org.briarproject.briar.android.threaded.ThreadListController;
|
||||||
import org.briarproject.briar.api.forum.Forum;
|
|
||||||
|
|
||||||
import androidx.annotation.UiThread;
|
import androidx.annotation.UiThread;
|
||||||
|
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
interface ForumController extends ThreadListController<Forum, ForumPostItem> {
|
interface ForumController extends ThreadListController<ForumPostItem> {
|
||||||
|
|
||||||
interface ForumListener extends ThreadListListener<ForumPostItem> {
|
interface ForumListener extends ThreadListListener<ForumPostItem> {
|
||||||
@UiThread
|
@UiThread
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ import org.briarproject.briar.android.threaded.ThreadListControllerImpl;
|
|||||||
import org.briarproject.briar.api.android.AndroidNotificationManager;
|
import org.briarproject.briar.api.android.AndroidNotificationManager;
|
||||||
import org.briarproject.briar.api.client.MessageTracker;
|
import org.briarproject.briar.api.client.MessageTracker;
|
||||||
import org.briarproject.briar.api.client.MessageTracker.GroupCount;
|
import org.briarproject.briar.api.client.MessageTracker.GroupCount;
|
||||||
import org.briarproject.briar.api.forum.Forum;
|
|
||||||
import org.briarproject.briar.api.forum.ForumInvitationResponse;
|
import org.briarproject.briar.api.forum.ForumInvitationResponse;
|
||||||
import org.briarproject.briar.api.forum.ForumManager;
|
import org.briarproject.briar.api.forum.ForumManager;
|
||||||
import org.briarproject.briar.api.forum.ForumPost;
|
import org.briarproject.briar.api.forum.ForumPost;
|
||||||
@@ -43,7 +42,7 @@ import static org.briarproject.bramble.util.LogUtils.logException;
|
|||||||
|
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
class ForumControllerImpl extends
|
class ForumControllerImpl extends
|
||||||
ThreadListControllerImpl<Forum, ForumPostItem, ForumPostHeader, ForumPost, ForumListener>
|
ThreadListControllerImpl<ForumPostItem, ForumPostHeader, ForumPost, ForumListener>
|
||||||
implements ForumController {
|
implements ForumController {
|
||||||
|
|
||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
@@ -98,16 +97,6 @@ class ForumControllerImpl extends
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Collection<ForumPostHeader> loadHeaders() throws DbException {
|
|
||||||
return forumManager.getPostHeaders(getGroupId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String loadMessageText(ForumPostHeader h) throws DbException {
|
|
||||||
return forumManager.getPostText(h.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void markRead(MessageId id) throws DbException {
|
protected void markRead(MessageId id) throws DbException {
|
||||||
forumManager.setReadFlag(getGroupId(), id, true);
|
forumManager.setReadFlag(getGroupId(), id, true);
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import android.widget.Toast;
|
|||||||
import org.briarproject.bramble.api.crypto.CryptoExecutor;
|
import org.briarproject.bramble.api.crypto.CryptoExecutor;
|
||||||
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
||||||
import org.briarproject.bramble.api.db.DbException;
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
|
import org.briarproject.bramble.api.db.Transaction;
|
||||||
import org.briarproject.bramble.api.db.TransactionManager;
|
import org.briarproject.bramble.api.db.TransactionManager;
|
||||||
import org.briarproject.bramble.api.event.Event;
|
import org.briarproject.bramble.api.event.Event;
|
||||||
import org.briarproject.bramble.api.event.EventBus;
|
import org.briarproject.bramble.api.event.EventBus;
|
||||||
@@ -18,10 +19,15 @@ import org.briarproject.bramble.api.system.Clock;
|
|||||||
import org.briarproject.briar.R;
|
import org.briarproject.briar.R;
|
||||||
import org.briarproject.briar.android.threaded.ThreadListViewModel;
|
import org.briarproject.briar.android.threaded.ThreadListViewModel;
|
||||||
import org.briarproject.briar.api.android.AndroidNotificationManager;
|
import org.briarproject.briar.api.android.AndroidNotificationManager;
|
||||||
|
import org.briarproject.briar.api.client.MessageTracker;
|
||||||
|
import org.briarproject.briar.api.client.PostHeader;
|
||||||
import org.briarproject.briar.api.forum.Forum;
|
import org.briarproject.briar.api.forum.Forum;
|
||||||
import org.briarproject.briar.api.forum.ForumManager;
|
import org.briarproject.briar.api.forum.ForumManager;
|
||||||
|
import org.briarproject.briar.api.forum.ForumPostHeader;
|
||||||
import org.briarproject.briar.api.forum.ForumSharingManager;
|
import org.briarproject.briar.api.forum.ForumSharingManager;
|
||||||
|
import org.briarproject.briar.client.MessageTreeImpl;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
@@ -33,11 +39,13 @@ import androidx.lifecycle.MutableLiveData;
|
|||||||
import static android.widget.Toast.LENGTH_SHORT;
|
import static android.widget.Toast.LENGTH_SHORT;
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
import static java.util.logging.Logger.getLogger;
|
import static java.util.logging.Logger.getLogger;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logDuration;
|
||||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.now;
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
class ForumViewModel extends ThreadListViewModel<Forum, ForumPostItem> {
|
class ForumViewModel extends ThreadListViewModel<ForumPostItem> {
|
||||||
|
|
||||||
private static final Logger LOG = getLogger(ForumViewModel.class.getName());
|
private static final Logger LOG = getLogger(ForumViewModel.class.getName());
|
||||||
|
|
||||||
@@ -54,12 +62,13 @@ class ForumViewModel extends ThreadListViewModel<Forum, ForumPostItem> {
|
|||||||
AndroidNotificationManager notificationManager,
|
AndroidNotificationManager notificationManager,
|
||||||
@CryptoExecutor Executor cryptoExecutor,
|
@CryptoExecutor Executor cryptoExecutor,
|
||||||
Clock clock,
|
Clock clock,
|
||||||
|
MessageTracker messageTracker,
|
||||||
EventBus eventBus,
|
EventBus eventBus,
|
||||||
ForumManager forumManager,
|
ForumManager forumManager,
|
||||||
ForumSharingManager forumSharingManager) {
|
ForumSharingManager forumSharingManager) {
|
||||||
super(application, dbExecutor, lifecycleManager, db, androidExecutor,
|
super(application, dbExecutor, lifecycleManager, db, androidExecutor,
|
||||||
identityManager, notificationManager, cryptoExecutor, clock,
|
identityManager, notificationManager, cryptoExecutor, clock,
|
||||||
eventBus);
|
messageTracker, eventBus);
|
||||||
this.forumManager = forumManager;
|
this.forumManager = forumManager;
|
||||||
this.forumSharingManager = forumSharingManager;
|
this.forumSharingManager = forumSharingManager;
|
||||||
}
|
}
|
||||||
@@ -82,6 +91,29 @@ class ForumViewModel extends ThreadListViewModel<Forum, ForumPostItem> {
|
|||||||
return forum;
|
return forum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadItems() {
|
||||||
|
loadList(txn -> {
|
||||||
|
long start = now();
|
||||||
|
List<ForumPostHeader> headers =
|
||||||
|
forumManager.getPostHeaders(txn, groupId);
|
||||||
|
logDuration(LOG, "Loading headers", start);
|
||||||
|
List<ForumPostItem> items =
|
||||||
|
buildItems(txn, headers, this::buildItem);
|
||||||
|
return new MessageTreeImpl<>(items).depthFirstOrder();
|
||||||
|
}, this::setItems);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ForumPostItem buildItem(ForumPostHeader header, String text) {
|
||||||
|
return new ForumPostItem(header, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String loadMessageText(Transaction txn, PostHeader header)
|
||||||
|
throws DbException {
|
||||||
|
return forumManager.getPostText(txn, header.getId());
|
||||||
|
}
|
||||||
|
|
||||||
void deleteForum() {
|
void deleteForum() {
|
||||||
runOnDbThread(() -> {
|
runOnDbThread(() -> {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import org.briarproject.briar.android.privategroup.reveal.RevealContactsActivity
|
|||||||
import org.briarproject.briar.android.threaded.ThreadListActivity;
|
import org.briarproject.briar.android.threaded.ThreadListActivity;
|
||||||
import org.briarproject.briar.android.threaded.ThreadListController;
|
import org.briarproject.briar.android.threaded.ThreadListController;
|
||||||
import org.briarproject.briar.android.threaded.ThreadListViewModel;
|
import org.briarproject.briar.android.threaded.ThreadListViewModel;
|
||||||
import org.briarproject.briar.api.privategroup.PrivateGroup;
|
|
||||||
import org.briarproject.briar.api.privategroup.Visibility;
|
import org.briarproject.briar.api.privategroup.Visibility;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@@ -41,7 +40,7 @@ import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_
|
|||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
public class GroupActivity extends
|
public class GroupActivity extends
|
||||||
ThreadListActivity<PrivateGroup, GroupMessageItem, GroupMessageAdapter>
|
ThreadListActivity<GroupMessageItem, GroupMessageAdapter>
|
||||||
implements GroupListener {
|
implements GroupListener {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@@ -65,12 +64,12 @@ public class GroupActivity extends
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ThreadListController<PrivateGroup, GroupMessageItem> getController() {
|
protected ThreadListController<GroupMessageItem> getController() {
|
||||||
return controller;
|
return controller;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ThreadListViewModel<PrivateGroup, GroupMessageItem> getViewModel() {
|
protected ThreadListViewModel<GroupMessageItem> getViewModel() {
|
||||||
return viewModel;
|
return viewModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,22 +102,11 @@ public class GroupActivity extends
|
|||||||
}
|
}
|
||||||
|
|
||||||
setGroupEnabled(false);
|
setGroupEnabled(false);
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected GroupMessageAdapter createAdapter(
|
|
||||||
LinearLayoutManager layoutManager) {
|
|
||||||
return new GroupMessageAdapter(this, layoutManager);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void loadItems() {
|
|
||||||
controller.isDissolved(
|
controller.isDissolved(
|
||||||
new UiResultExceptionHandler<Boolean, DbException>(this) {
|
new UiResultExceptionHandler<Boolean, DbException>(this) {
|
||||||
@Override
|
@Override
|
||||||
public void onResultUi(Boolean isDissolved) {
|
public void onResultUi(Boolean isDissolved) {
|
||||||
setGroupEnabled(!isDissolved);
|
setGroupEnabled(!isDissolved);
|
||||||
GroupActivity.super.loadItems();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -128,6 +116,12 @@ public class GroupActivity extends
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected GroupMessageAdapter createAdapter(
|
||||||
|
LinearLayoutManager layoutManager) {
|
||||||
|
return new GroupMessageAdapter(this, layoutManager);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreateOptionsMenu(Menu menu) {
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
// Inflate the menu items for use in the action bar
|
// Inflate the menu items for use in the action bar
|
||||||
|
|||||||
@@ -5,13 +5,12 @@ import org.briarproject.bramble.api.db.DbException;
|
|||||||
import org.briarproject.bramble.api.identity.AuthorId;
|
import org.briarproject.bramble.api.identity.AuthorId;
|
||||||
import org.briarproject.briar.android.controller.handler.ResultExceptionHandler;
|
import org.briarproject.briar.android.controller.handler.ResultExceptionHandler;
|
||||||
import org.briarproject.briar.android.threaded.ThreadListController;
|
import org.briarproject.briar.android.threaded.ThreadListController;
|
||||||
import org.briarproject.briar.api.privategroup.PrivateGroup;
|
|
||||||
import org.briarproject.briar.api.privategroup.Visibility;
|
import org.briarproject.briar.api.privategroup.Visibility;
|
||||||
|
|
||||||
import androidx.annotation.UiThread;
|
import androidx.annotation.UiThread;
|
||||||
|
|
||||||
public interface GroupController
|
public interface GroupController
|
||||||
extends ThreadListController<PrivateGroup, GroupMessageItem> {
|
extends ThreadListController<GroupMessageItem> {
|
||||||
|
|
||||||
void isDissolved(
|
void isDissolved(
|
||||||
ResultExceptionHandler<Boolean, DbException> handler);
|
ResultExceptionHandler<Boolean, DbException> handler);
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ import org.briarproject.briar.api.privategroup.GroupMessage;
|
|||||||
import org.briarproject.briar.api.privategroup.GroupMessageFactory;
|
import org.briarproject.briar.api.privategroup.GroupMessageFactory;
|
||||||
import org.briarproject.briar.api.privategroup.GroupMessageHeader;
|
import org.briarproject.briar.api.privategroup.GroupMessageHeader;
|
||||||
import org.briarproject.briar.api.privategroup.JoinMessageHeader;
|
import org.briarproject.briar.api.privategroup.JoinMessageHeader;
|
||||||
import org.briarproject.briar.api.privategroup.PrivateGroup;
|
|
||||||
import org.briarproject.briar.api.privategroup.PrivateGroupManager;
|
import org.briarproject.briar.api.privategroup.PrivateGroupManager;
|
||||||
import org.briarproject.briar.api.privategroup.event.ContactRelationshipRevealedEvent;
|
import org.briarproject.briar.api.privategroup.event.ContactRelationshipRevealedEvent;
|
||||||
import org.briarproject.briar.api.privategroup.event.GroupDissolvedEvent;
|
import org.briarproject.briar.api.privategroup.event.GroupDissolvedEvent;
|
||||||
@@ -47,7 +46,7 @@ import static org.briarproject.bramble.util.LogUtils.logException;
|
|||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
class GroupControllerImpl extends
|
class GroupControllerImpl extends
|
||||||
ThreadListControllerImpl<PrivateGroup, GroupMessageItem, GroupMessageHeader, GroupMessage, GroupListener>
|
ThreadListControllerImpl<GroupMessageItem, GroupMessageHeader, GroupMessage, GroupListener>
|
||||||
implements GroupController {
|
implements GroupController {
|
||||||
|
|
||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
@@ -108,21 +107,6 @@ class GroupControllerImpl extends
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Collection<GroupMessageHeader> loadHeaders() throws DbException {
|
|
||||||
return privateGroupManager.getHeaders(getGroupId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String loadMessageText(GroupMessageHeader header)
|
|
||||||
throws DbException {
|
|
||||||
if (header instanceof JoinMessageHeader) {
|
|
||||||
// will be looked up later
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
return privateGroupManager.getMessageText(header.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void markRead(MessageId id) throws DbException {
|
protected void markRead(MessageId id) throws DbException {
|
||||||
privateGroupManager.setReadFlag(getGroupId(), id, true);
|
privateGroupManager.setReadFlag(getGroupId(), id, true);
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ class GroupMessageAdapter extends ThreadItemAdapter<GroupMessageItem> {
|
|||||||
@LayoutRes
|
@LayoutRes
|
||||||
@Override
|
@Override
|
||||||
public int getItemViewType(int position) {
|
public int getItemViewType(int position) {
|
||||||
GroupMessageItem item = items.get(position);
|
GroupMessageItem item = getItem(position);
|
||||||
return item.getLayout();
|
return item.getLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,7 +55,7 @@ class GroupMessageAdapter extends ThreadItemAdapter<GroupMessageItem> {
|
|||||||
void updateVisibility(AuthorId memberId, Visibility v) {
|
void updateVisibility(AuthorId memberId, Visibility v) {
|
||||||
int position = findItemPosition(memberId);
|
int position = findItemPosition(memberId);
|
||||||
if (position != NO_POSITION) {
|
if (position != NO_POSITION) {
|
||||||
GroupMessageItem item = items.get(position);
|
GroupMessageItem item = getItem(position);
|
||||||
if (item instanceof JoinMessageItem) {
|
if (item instanceof JoinMessageItem) {
|
||||||
((JoinMessageItem) item).setVisibility(v);
|
((JoinMessageItem) item).setVisibility(v);
|
||||||
notifyItemChanged(findItemPosition(item), item);
|
notifyItemChanged(findItemPosition(item), item);
|
||||||
@@ -63,14 +63,22 @@ class GroupMessageAdapter extends ThreadItemAdapter<GroupMessageItem> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
private int findItemPosition(AuthorId a) {
|
private int findItemPosition(AuthorId a) {
|
||||||
int count = items.size();
|
for (int i = 0; i < getItemCount(); i++) {
|
||||||
for (int i = 0; i < count; i++) {
|
GroupMessageItem item = getItem(i);
|
||||||
GroupMessageItem item = items.get(i);
|
|
||||||
if (item.getAuthor().getId().equals(a))
|
if (item.getAuthor().getId().equals(a))
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
return NO_POSITION; // Not found
|
return NO_POSITION; // Not found
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
private int findItemPosition(GroupMessageItem itemToFind) {
|
||||||
|
for (int i = 0; i < getItemCount(); i++) {
|
||||||
|
if (getItem(i).equals(itemToFind)) return i;
|
||||||
|
}
|
||||||
|
return NO_POSITION; // Not found
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import android.app.Application;
|
|||||||
import org.briarproject.bramble.api.crypto.CryptoExecutor;
|
import org.briarproject.bramble.api.crypto.CryptoExecutor;
|
||||||
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
||||||
import org.briarproject.bramble.api.db.DbException;
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
|
import org.briarproject.bramble.api.db.Transaction;
|
||||||
import org.briarproject.bramble.api.db.TransactionManager;
|
import org.briarproject.bramble.api.db.TransactionManager;
|
||||||
import org.briarproject.bramble.api.event.Event;
|
import org.briarproject.bramble.api.event.Event;
|
||||||
import org.briarproject.bramble.api.event.EventBus;
|
import org.briarproject.bramble.api.event.EventBus;
|
||||||
@@ -18,10 +19,16 @@ import org.briarproject.bramble.api.system.AndroidExecutor;
|
|||||||
import org.briarproject.bramble.api.system.Clock;
|
import org.briarproject.bramble.api.system.Clock;
|
||||||
import org.briarproject.briar.android.threaded.ThreadListViewModel;
|
import org.briarproject.briar.android.threaded.ThreadListViewModel;
|
||||||
import org.briarproject.briar.api.android.AndroidNotificationManager;
|
import org.briarproject.briar.api.android.AndroidNotificationManager;
|
||||||
|
import org.briarproject.briar.api.client.MessageTracker;
|
||||||
|
import org.briarproject.briar.api.client.PostHeader;
|
||||||
import org.briarproject.briar.api.privategroup.GroupMessageFactory;
|
import org.briarproject.briar.api.privategroup.GroupMessageFactory;
|
||||||
|
import org.briarproject.briar.api.privategroup.GroupMessageHeader;
|
||||||
|
import org.briarproject.briar.api.privategroup.JoinMessageHeader;
|
||||||
import org.briarproject.briar.api.privategroup.PrivateGroup;
|
import org.briarproject.briar.api.privategroup.PrivateGroup;
|
||||||
import org.briarproject.briar.api.privategroup.PrivateGroupManager;
|
import org.briarproject.briar.api.privategroup.PrivateGroupManager;
|
||||||
|
import org.briarproject.briar.client.MessageTreeImpl;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
@@ -32,20 +39,22 @@ import androidx.lifecycle.MutableLiveData;
|
|||||||
|
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
import static java.util.logging.Logger.getLogger;
|
import static java.util.logging.Logger.getLogger;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logDuration;
|
||||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.now;
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
class GroupViewModel
|
class GroupViewModel extends ThreadListViewModel<GroupMessageItem> {
|
||||||
extends ThreadListViewModel<PrivateGroup, GroupMessageItem> {
|
|
||||||
|
|
||||||
private static final Logger LOG = getLogger(GroupViewModel.class.getName());
|
private static final Logger LOG = getLogger(GroupViewModel.class.getName());
|
||||||
|
|
||||||
private final PrivateGroupManager privateGroupManager;
|
private final PrivateGroupManager privateGroupManager;
|
||||||
private final GroupMessageFactory groupMessageFactory;
|
private final GroupMessageFactory groupMessageFactory;
|
||||||
|
|
||||||
MutableLiveData<PrivateGroup> privateGroup = new MutableLiveData<>();
|
private final MutableLiveData<PrivateGroup> privateGroup =
|
||||||
MutableLiveData<Boolean> isCreator = new MutableLiveData<>();
|
new MutableLiveData<>();
|
||||||
|
private final MutableLiveData<Boolean> isCreator = new MutableLiveData<>();
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
GroupViewModel(Application application,
|
GroupViewModel(Application application,
|
||||||
@@ -58,11 +67,12 @@ class GroupViewModel
|
|||||||
AndroidNotificationManager notificationManager,
|
AndroidNotificationManager notificationManager,
|
||||||
@CryptoExecutor Executor cryptoExecutor,
|
@CryptoExecutor Executor cryptoExecutor,
|
||||||
Clock clock,
|
Clock clock,
|
||||||
|
MessageTracker messageTracker,
|
||||||
PrivateGroupManager privateGroupManager,
|
PrivateGroupManager privateGroupManager,
|
||||||
GroupMessageFactory groupMessageFactory) {
|
GroupMessageFactory groupMessageFactory) {
|
||||||
super(application, dbExecutor, lifecycleManager, db, androidExecutor,
|
super(application, dbExecutor, lifecycleManager, db, androidExecutor,
|
||||||
identityManager, notificationManager, cryptoExecutor, clock,
|
identityManager, notificationManager, cryptoExecutor, clock,
|
||||||
eventBus);
|
messageTracker, eventBus);
|
||||||
this.privateGroupManager = privateGroupManager;
|
this.privateGroupManager = privateGroupManager;
|
||||||
this.groupMessageFactory = groupMessageFactory;
|
this.groupMessageFactory = groupMessageFactory;
|
||||||
}
|
}
|
||||||
@@ -91,6 +101,37 @@ class GroupViewModel
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadItems() {
|
||||||
|
loadList(txn -> {
|
||||||
|
// TODO first check if group is dissolved
|
||||||
|
long start = now();
|
||||||
|
List<GroupMessageHeader> headers =
|
||||||
|
privateGroupManager.getHeaders(txn, groupId);
|
||||||
|
logDuration(LOG, "Loading headers", start);
|
||||||
|
List<GroupMessageItem> items =
|
||||||
|
buildItems(txn, headers, this::buildItem);
|
||||||
|
return new MessageTreeImpl<>(items).depthFirstOrder();
|
||||||
|
}, this::setItems);
|
||||||
|
}
|
||||||
|
|
||||||
|
private GroupMessageItem buildItem(GroupMessageHeader header, String text) {
|
||||||
|
if (header instanceof JoinMessageHeader) {
|
||||||
|
return new JoinMessageItem((JoinMessageHeader) header, text);
|
||||||
|
}
|
||||||
|
return new GroupMessageItem(header, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String loadMessageText(
|
||||||
|
Transaction txn, PostHeader header) throws DbException {
|
||||||
|
if (header instanceof JoinMessageHeader) {
|
||||||
|
// will be looked up later
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return privateGroupManager.getMessageText(txn, header.getId());
|
||||||
|
}
|
||||||
|
|
||||||
void deletePrivateGroup() {
|
void deletePrivateGroup() {
|
||||||
runOnDbThread(() -> {
|
runOnDbThread(() -> {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -1,54 +0,0 @@
|
|||||||
package org.briarproject.briar.android.threaded;
|
|
||||||
|
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
|
||||||
import org.briarproject.bramble.api.sync.MessageId;
|
|
||||||
import org.briarproject.briar.api.client.MessageTree;
|
|
||||||
import org.briarproject.briar.api.client.MessageTree.MessageNode;
|
|
||||||
import org.briarproject.briar.client.MessageTreeImpl;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import androidx.annotation.UiThread;
|
|
||||||
|
|
||||||
@UiThread
|
|
||||||
@NotNullByDefault
|
|
||||||
public class NestedTreeList<T extends MessageNode> implements Iterable<T> {
|
|
||||||
|
|
||||||
private final MessageTree<T> tree = new MessageTreeImpl<>();
|
|
||||||
private List<T> depthFirstCollection = new ArrayList<>();
|
|
||||||
|
|
||||||
public void addAll(Collection<T> collection) {
|
|
||||||
tree.add(collection);
|
|
||||||
depthFirstCollection = new ArrayList<>(tree.depthFirstOrder());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void add(T elem) {
|
|
||||||
tree.add(elem);
|
|
||||||
depthFirstCollection = new ArrayList<>(tree.depthFirstOrder());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clear() {
|
|
||||||
tree.clear();
|
|
||||||
depthFirstCollection.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public T get(int index) {
|
|
||||||
return depthFirstCollection.get(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int size() {
|
|
||||||
return depthFirstCollection.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean contains(MessageId m) {
|
|
||||||
return tree.contains(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Iterator<T> iterator() {
|
|
||||||
return depthFirstCollection.iterator();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -99,4 +99,14 @@ public abstract class ThreadItem implements MessageNode {
|
|||||||
return highlighted;
|
return highlighted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return messageId.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(@Nullable Object o) {
|
||||||
|
return o instanceof ThreadItem &&
|
||||||
|
messageId.equals(((ThreadItem) o).messageId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,37 +4,48 @@ import android.view.LayoutInflater;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||||
|
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||||
import org.briarproject.bramble.api.sync.MessageId;
|
import org.briarproject.bramble.api.sync.MessageId;
|
||||||
import org.briarproject.briar.R;
|
import org.briarproject.briar.R;
|
||||||
import org.briarproject.briar.android.util.ItemReturningAdapter;
|
import org.briarproject.briar.android.util.ItemReturningAdapter;
|
||||||
import org.briarproject.briar.android.util.VersionedAdapter;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.UiThread;
|
import androidx.annotation.UiThread;
|
||||||
|
import androidx.recyclerview.widget.DiffUtil;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.ListAdapter;
|
||||||
|
|
||||||
import static androidx.recyclerview.widget.RecyclerView.NO_POSITION;
|
import static androidx.recyclerview.widget.RecyclerView.NO_POSITION;
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
|
@MethodsNotNullByDefault
|
||||||
|
@ParametersNotNullByDefault
|
||||||
public class ThreadItemAdapter<I extends ThreadItem>
|
public class ThreadItemAdapter<I extends ThreadItem>
|
||||||
extends RecyclerView.Adapter<BaseThreadItemViewHolder<I>>
|
extends ListAdapter<I, BaseThreadItemViewHolder<I>>
|
||||||
implements VersionedAdapter, ItemReturningAdapter<I> {
|
implements ItemReturningAdapter<I> {
|
||||||
|
|
||||||
static final int UNDEFINED = -1;
|
static final int UNDEFINED = -1;
|
||||||
|
|
||||||
protected final NestedTreeList<I> items = new NestedTreeList<>();
|
|
||||||
private final ThreadItemListener<I> listener;
|
private final ThreadItemListener<I> listener;
|
||||||
private final LinearLayoutManager layoutManager;
|
private final LinearLayoutManager layoutManager;
|
||||||
|
|
||||||
private volatile int revision = 0;
|
|
||||||
|
|
||||||
public ThreadItemAdapter(ThreadItemListener<I> listener,
|
public ThreadItemAdapter(ThreadItemListener<I> listener,
|
||||||
LinearLayoutManager layoutManager) {
|
LinearLayoutManager layoutManager) {
|
||||||
|
super(new DiffUtil.ItemCallback<I>() {
|
||||||
|
@Override
|
||||||
|
public boolean areItemsTheSame(I a, I b) {
|
||||||
|
return a.equals(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean areContentsTheSame(I a, I b) {
|
||||||
|
return a.isHighlighted() == b.isHighlighted() &&
|
||||||
|
a.isRead() && b.isRead();
|
||||||
|
}
|
||||||
|
});
|
||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
this.layoutManager = layoutManager;
|
this.layoutManager = layoutManager;
|
||||||
}
|
}
|
||||||
@@ -51,28 +62,14 @@ public class ThreadItemAdapter<I extends ThreadItem>
|
|||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(@NonNull BaseThreadItemViewHolder<I> ui,
|
public void onBindViewHolder(@NonNull BaseThreadItemViewHolder<I> ui,
|
||||||
int position) {
|
int position) {
|
||||||
I item = items.get(position);
|
I item = getItem(position);
|
||||||
ui.bind(item, listener);
|
ui.bind(item, listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getItemCount() {
|
|
||||||
return items.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getRevision() {
|
|
||||||
return revision;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void incrementRevision() {
|
|
||||||
revision++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setItemWithIdVisible(MessageId messageId) {
|
void setItemWithIdVisible(MessageId messageId) {
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
for (I item : items) {
|
for (int i = 0; i < getItemCount(); i++) {
|
||||||
|
I item = getItem(i);
|
||||||
if (item.getId().equals(messageId)) {
|
if (item.getId().equals(messageId)) {
|
||||||
layoutManager.scrollToPosition(pos);
|
layoutManager.scrollToPosition(pos);
|
||||||
break;
|
break;
|
||||||
@@ -81,46 +78,16 @@ public class ThreadItemAdapter<I extends ThreadItem>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setItems(Collection<I> items) {
|
|
||||||
this.items.clear();
|
|
||||||
this.items.addAll(items);
|
|
||||||
notifyDataSetChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void add(I item) {
|
|
||||||
items.add(item);
|
|
||||||
notifyItemInserted(findItemPosition(item));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public I getItemAt(int position) {
|
|
||||||
if (position == NO_POSITION || position >= items.size()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return items.get(position);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected int findItemPosition(@Nullable I item) {
|
|
||||||
for (int i = 0; i < items.size(); i++) {
|
|
||||||
if (items.get(i).equals(item)) return i;
|
|
||||||
}
|
|
||||||
return NO_POSITION; // Not found
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean contains(MessageId m) {
|
|
||||||
return items.contains(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Highlights the item with the given {@link MessageId}
|
* Highlights the item with the given {@link MessageId}
|
||||||
* and disables the highlight for a previously highlighted item, if any.
|
* and disables the highlight for a previously highlighted item, if any.
|
||||||
*
|
* <p>
|
||||||
* Only one item can be highlighted at a time.
|
* Only one item can be highlighted at a time.
|
||||||
*/
|
*/
|
||||||
void setHighlightedItem(@Nullable MessageId id) {
|
void setHighlightedItem(@Nullable MessageId id) {
|
||||||
for (int i = 0; i < items.size(); i++) {
|
for (int i = 0; i < getItemCount(); i++) {
|
||||||
I item = items.get(i);
|
I item = getItem(i);
|
||||||
if (id != null && item.getId().equals(id)) {
|
if (item.getId().equals(id)) {
|
||||||
item.setHighlighted(true);
|
item.setHighlighted(true);
|
||||||
notifyItemChanged(i, item);
|
notifyItemChanged(i, item);
|
||||||
} else if (item.isHighlighted()) {
|
} else if (item.isHighlighted()) {
|
||||||
@@ -132,8 +99,9 @@ public class ThreadItemAdapter<I extends ThreadItem>
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
I getHighlightedItem() {
|
I getHighlightedItem() {
|
||||||
for (I i : items) {
|
for (int i = 0; i < getItemCount(); i++) {
|
||||||
if (i.isHighlighted()) return i;
|
I item = getItem(i);
|
||||||
|
if (item.isHighlighted()) return item;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -144,8 +112,8 @@ public class ThreadItemAdapter<I extends ThreadItem>
|
|||||||
int getVisibleUnreadPosBottom() {
|
int getVisibleUnreadPosBottom() {
|
||||||
int positionBottom = layoutManager.findLastVisibleItemPosition();
|
int positionBottom = layoutManager.findLastVisibleItemPosition();
|
||||||
if (positionBottom == NO_POSITION) return NO_POSITION;
|
if (positionBottom == NO_POSITION) return NO_POSITION;
|
||||||
for (int i = positionBottom + 1; i < items.size(); i++) {
|
for (int i = positionBottom + 1; i < getItemCount(); i++) {
|
||||||
if (!items.get(i).isRead()) return i;
|
if (!getItem(i).isRead()) return i;
|
||||||
}
|
}
|
||||||
return NO_POSITION;
|
return NO_POSITION;
|
||||||
}
|
}
|
||||||
@@ -156,8 +124,8 @@ public class ThreadItemAdapter<I extends ThreadItem>
|
|||||||
int getVisibleUnreadPosTop() {
|
int getVisibleUnreadPosTop() {
|
||||||
int positionTop = layoutManager.findFirstVisibleItemPosition();
|
int positionTop = layoutManager.findFirstVisibleItemPosition();
|
||||||
int position = NO_POSITION;
|
int position = NO_POSITION;
|
||||||
for (int i = 0; i < items.size(); i++) {
|
for (int i = 0; i < getItemCount(); i++) {
|
||||||
if (i < positionTop && !items.get(i).isRead()) {
|
if (i < positionTop && !getItem(i).isRead()) {
|
||||||
position = i;
|
position = i;
|
||||||
} else if (i >= positionTop) {
|
} else if (i >= positionTop) {
|
||||||
return position;
|
return position;
|
||||||
@@ -166,6 +134,11 @@ public class ThreadItemAdapter<I extends ThreadItem>
|
|||||||
return NO_POSITION;
|
return NO_POSITION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public I getItemAt(int position) {
|
||||||
|
return getItem(position);
|
||||||
|
}
|
||||||
|
|
||||||
public interface ThreadItemListener<I> {
|
public interface ThreadItemListener<I> {
|
||||||
void onReplyClick(I item);
|
void onReplyClick(I item);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ import org.briarproject.briar.android.view.TextSendController;
|
|||||||
import org.briarproject.briar.android.view.TextSendController.SendListener;
|
import org.briarproject.briar.android.view.TextSendController.SendListener;
|
||||||
import org.briarproject.briar.android.view.UnreadMessageButton;
|
import org.briarproject.briar.android.view.UnreadMessageButton;
|
||||||
import org.briarproject.briar.api.attachment.AttachmentHeader;
|
import org.briarproject.briar.api.attachment.AttachmentHeader;
|
||||||
import org.briarproject.briar.api.client.NamedGroup;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -48,7 +47,7 @@ import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty;
|
|||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
public abstract class ThreadListActivity<G extends NamedGroup, I extends ThreadItem, A extends ThreadItemAdapter<I>>
|
public abstract class ThreadListActivity<I extends ThreadItem, A extends ThreadItemAdapter<I>>
|
||||||
extends BriarActivity
|
extends BriarActivity
|
||||||
implements ThreadListListener<I>, SendListener, SharingListener,
|
implements ThreadListListener<I>, SendListener, SharingListener,
|
||||||
ThreadItemListener<I>, ThreadListDataSource {
|
ThreadItemListener<I>, ThreadListDataSource {
|
||||||
@@ -59,6 +58,7 @@ public abstract class ThreadListActivity<G extends NamedGroup, I extends ThreadI
|
|||||||
getLogger(ThreadListActivity.class.getName());
|
getLogger(ThreadListActivity.class.getName());
|
||||||
|
|
||||||
protected A adapter;
|
protected A adapter;
|
||||||
|
|
||||||
private ThreadScrollListener<I> scrollListener;
|
private ThreadScrollListener<I> scrollListener;
|
||||||
protected BriarRecyclerView list;
|
protected BriarRecyclerView list;
|
||||||
private LinearLayoutManager layoutManager;
|
private LinearLayoutManager layoutManager;
|
||||||
@@ -70,9 +70,9 @@ public abstract class ThreadListActivity<G extends NamedGroup, I extends ThreadI
|
|||||||
@Nullable
|
@Nullable
|
||||||
private MessageId replyId;
|
private MessageId replyId;
|
||||||
|
|
||||||
protected abstract ThreadListController<G, I> getController();
|
protected abstract ThreadListController<I> getController();
|
||||||
|
|
||||||
protected abstract ThreadListViewModel<G, I> getViewModel();
|
protected abstract ThreadListViewModel<I> getViewModel();
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
protected SharingController sharingController;
|
protected SharingController sharingController;
|
||||||
@@ -127,6 +127,11 @@ public abstract class ThreadListActivity<G extends NamedGroup, I extends ThreadI
|
|||||||
if (replyIdBytes != null) replyId = new MessageId(replyIdBytes);
|
if (replyIdBytes != null) replyId = new MessageId(replyIdBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getViewModel().getItems().observe(this, result -> result
|
||||||
|
.onError(this::handleException)
|
||||||
|
.onSuccess(this::displayItems)
|
||||||
|
);
|
||||||
|
|
||||||
sharingController.setSharingListener(this);
|
sharingController.setSharingListener(this);
|
||||||
loadSharingContacts();
|
loadSharingContacts();
|
||||||
}
|
}
|
||||||
@@ -145,44 +150,22 @@ public abstract class ThreadListActivity<G extends NamedGroup, I extends ThreadI
|
|||||||
|
|
||||||
protected abstract A createAdapter(LinearLayoutManager layoutManager);
|
protected abstract A createAdapter(LinearLayoutManager layoutManager);
|
||||||
|
|
||||||
protected void loadItems() {
|
protected void displayItems(List<I> items) {
|
||||||
int revision = adapter.getRevision();
|
if (items.isEmpty()) {
|
||||||
getController().loadItems(
|
list.showData();
|
||||||
new UiResultExceptionHandler<ThreadItemList<I>, DbException>(
|
|
||||||
this) {
|
|
||||||
@Override
|
|
||||||
public void onResultUi(ThreadItemList<I> items) {
|
|
||||||
if (revision == adapter.getRevision()) {
|
|
||||||
adapter.incrementRevision();
|
|
||||||
if (items.isEmpty()) {
|
|
||||||
list.showData();
|
|
||||||
} else {
|
|
||||||
displayItems(items);
|
|
||||||
updateTextInput();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
LOG.info("Concurrent update, reloading");
|
|
||||||
loadItems();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onExceptionUi(DbException exception) {
|
|
||||||
handleException(exception);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void displayItems(ThreadItemList<I> items) {
|
|
||||||
adapter.setItems(items);
|
|
||||||
MessageId messageId = items.getFirstVisibleItemId();
|
|
||||||
if (messageId != null)
|
|
||||||
adapter.setItemWithIdVisible(messageId);
|
|
||||||
list.showData();
|
|
||||||
if (layoutManagerState == null) {
|
|
||||||
list.scrollToPosition(0); // Scroll to the top
|
|
||||||
} else {
|
} else {
|
||||||
layoutManager.onRestoreInstanceState(layoutManagerState);
|
adapter.submitList(items);
|
||||||
|
// TODO get this ID from elsewhere
|
||||||
|
MessageId messageId = null; // items.getFirstVisibleItemId();
|
||||||
|
if (messageId != null)
|
||||||
|
adapter.setItemWithIdVisible(messageId);
|
||||||
|
list.showData();
|
||||||
|
if (layoutManagerState == null) {
|
||||||
|
list.scrollToPosition(0); // Scroll to the top
|
||||||
|
} else {
|
||||||
|
layoutManager.onRestoreInstanceState(layoutManagerState);
|
||||||
|
}
|
||||||
|
updateTextInput();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,7 +192,6 @@ public abstract class ThreadListActivity<G extends NamedGroup, I extends ThreadI
|
|||||||
public void onStart() {
|
public void onStart() {
|
||||||
super.onStart();
|
super.onStart();
|
||||||
sharingController.onStart();
|
sharingController.onStart();
|
||||||
loadItems();
|
|
||||||
list.startPeriodicUpdate();
|
list.startPeriodicUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -296,7 +278,7 @@ public abstract class ThreadListActivity<G extends NamedGroup, I extends ThreadI
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void scrollToItemAtTop(I item) {
|
private void scrollToItemAtTop(I item) {
|
||||||
int position = adapter.findItemPosition(item);
|
int position = NO_POSITION;// adapter.findItemPosition(item);
|
||||||
if (position != NO_POSITION) {
|
if (position != NO_POSITION) {
|
||||||
layoutManager
|
layoutManager
|
||||||
.scrollToPositionWithOffset(position, 0);
|
.scrollToPositionWithOffset(position, 0);
|
||||||
@@ -357,15 +339,14 @@ public abstract class ThreadListActivity<G extends NamedGroup, I extends ThreadI
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void addItem(I item, boolean isLocal) {
|
private void addItem(I item, boolean isLocal) {
|
||||||
adapter.incrementRevision();
|
|
||||||
MessageId parent = item.getParentId();
|
MessageId parent = item.getParentId();
|
||||||
if (parent != null && !adapter.contains(parent)) {
|
if (parent != null) {
|
||||||
// We've incremented the adapter's revision, so the item will be
|
// We've incremented the adapter's revision, so the item will be
|
||||||
// loaded when its parent has been loaded
|
// loaded when its parent has been loaded
|
||||||
LOG.info("Ignoring item with missing parent");
|
LOG.info("Ignoring item with missing parent");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
adapter.add(item);
|
// TODO submit new list
|
||||||
|
|
||||||
if (isLocal) {
|
if (isLocal) {
|
||||||
scrollToItemAtTop(item);
|
scrollToItemAtTop(item);
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import org.briarproject.bramble.api.sync.GroupId;
|
|||||||
import org.briarproject.bramble.api.sync.MessageId;
|
import org.briarproject.bramble.api.sync.MessageId;
|
||||||
import org.briarproject.briar.android.controller.ActivityLifecycleController;
|
import org.briarproject.briar.android.controller.ActivityLifecycleController;
|
||||||
import org.briarproject.briar.android.controller.handler.ResultExceptionHandler;
|
import org.briarproject.briar.android.controller.handler.ResultExceptionHandler;
|
||||||
import org.briarproject.briar.api.client.NamedGroup;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
@@ -16,7 +15,7 @@ import javax.annotation.Nullable;
|
|||||||
import androidx.annotation.UiThread;
|
import androidx.annotation.UiThread;
|
||||||
|
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
public interface ThreadListController<G extends NamedGroup, I extends ThreadItem>
|
public interface ThreadListController<I extends ThreadItem>
|
||||||
extends ActivityLifecycleController {
|
extends ActivityLifecycleController {
|
||||||
|
|
||||||
void setGroupId(GroupId groupId);
|
void setGroupId(GroupId groupId);
|
||||||
@@ -24,9 +23,6 @@ public interface ThreadListController<G extends NamedGroup, I extends ThreadItem
|
|||||||
void loadSharingContacts(
|
void loadSharingContacts(
|
||||||
ResultExceptionHandler<Collection<ContactId>, DbException> handler);
|
ResultExceptionHandler<Collection<ContactId>, DbException> handler);
|
||||||
|
|
||||||
void loadItems(
|
|
||||||
ResultExceptionHandler<ThreadItemList<I>, DbException> handler);
|
|
||||||
|
|
||||||
void markItemRead(I item);
|
void markItemRead(I item);
|
||||||
|
|
||||||
void markItemsRead(Collection<I> items);
|
void markItemsRead(Collection<I> items);
|
||||||
@@ -48,7 +44,8 @@ public interface ThreadListController<G extends NamedGroup, I extends ThreadItem
|
|||||||
|
|
||||||
interface ThreadListDataSource {
|
interface ThreadListDataSource {
|
||||||
|
|
||||||
@UiThread @Nullable
|
@UiThread
|
||||||
|
@Nullable
|
||||||
MessageId getFirstVisibleMessageId();
|
MessageId getFirstVisibleMessageId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import org.briarproject.briar.android.controller.handler.ResultExceptionHandler;
|
|||||||
import org.briarproject.briar.android.threaded.ThreadListController.ThreadListListener;
|
import org.briarproject.briar.android.threaded.ThreadListController.ThreadListListener;
|
||||||
import org.briarproject.briar.api.android.AndroidNotificationManager;
|
import org.briarproject.briar.api.android.AndroidNotificationManager;
|
||||||
import org.briarproject.briar.api.client.MessageTracker;
|
import org.briarproject.briar.api.client.MessageTracker;
|
||||||
import org.briarproject.briar.api.client.NamedGroup;
|
|
||||||
import org.briarproject.briar.api.client.PostHeader;
|
import org.briarproject.briar.api.client.PostHeader;
|
||||||
import org.briarproject.briar.api.client.ThreadedMessage;
|
import org.briarproject.briar.api.client.ThreadedMessage;
|
||||||
|
|
||||||
@@ -34,7 +33,6 @@ import java.util.logging.Logger;
|
|||||||
|
|
||||||
import androidx.annotation.CallSuper;
|
import androidx.annotation.CallSuper;
|
||||||
|
|
||||||
import static java.util.logging.Level.INFO;
|
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
import static org.briarproject.bramble.util.LogUtils.logDuration;
|
import static org.briarproject.bramble.util.LogUtils.logDuration;
|
||||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
@@ -42,9 +40,9 @@ import static org.briarproject.bramble.util.LogUtils.now;
|
|||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
public abstract class ThreadListControllerImpl<G extends NamedGroup, I extends ThreadItem, H extends PostHeader, M extends ThreadedMessage, L extends ThreadListListener<I>>
|
public abstract class ThreadListControllerImpl<I extends ThreadItem, H extends PostHeader, M extends ThreadedMessage, L extends ThreadListListener<I>>
|
||||||
extends DbControllerImpl
|
extends DbControllerImpl
|
||||||
implements ThreadListController<G, I>, EventListener {
|
implements ThreadListController<I>, EventListener {
|
||||||
|
|
||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
Logger.getLogger(ThreadListControllerImpl.class.getName());
|
Logger.getLogger(ThreadListControllerImpl.class.getName());
|
||||||
@@ -129,42 +127,6 @@ public abstract class ThreadListControllerImpl<G extends NamedGroup, I extends T
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void loadItems(
|
|
||||||
ResultExceptionHandler<ThreadItemList<I>, DbException> handler) {
|
|
||||||
checkGroupId();
|
|
||||||
runOnDbThread(() -> {
|
|
||||||
try {
|
|
||||||
// Load headers
|
|
||||||
long start = now();
|
|
||||||
Collection<H> headers = loadHeaders();
|
|
||||||
logDuration(LOG, "Loading headers", start);
|
|
||||||
|
|
||||||
// Load bodies into cache
|
|
||||||
start = now();
|
|
||||||
for (H header : headers) {
|
|
||||||
if (!textCache.containsKey(header.getId())) {
|
|
||||||
textCache.put(header.getId(),
|
|
||||||
loadMessageText(header));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
logDuration(LOG, "Loading bodies", start);
|
|
||||||
|
|
||||||
// Build and hand over items
|
|
||||||
handler.onResult(buildItems(headers));
|
|
||||||
} catch (DbException e) {
|
|
||||||
logException(LOG, WARNING, e);
|
|
||||||
handler.onException(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@DatabaseExecutor
|
|
||||||
protected abstract Collection<H> loadHeaders() throws DbException;
|
|
||||||
|
|
||||||
@DatabaseExecutor
|
|
||||||
protected abstract String loadMessageText(H header) throws DbException;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void markItemRead(I item) {
|
public void markItemRead(I item) {
|
||||||
markItemsRead(Collections.singletonList(item));
|
markItemsRead(Collections.singletonList(item));
|
||||||
@@ -207,19 +169,6 @@ public abstract class ThreadListControllerImpl<G extends NamedGroup, I extends T
|
|||||||
@DatabaseExecutor
|
@DatabaseExecutor
|
||||||
protected abstract H addLocalMessage(M message) throws DbException;
|
protected abstract H addLocalMessage(M message) throws DbException;
|
||||||
|
|
||||||
private ThreadItemList<I> buildItems(Collection<H> headers)
|
|
||||||
throws DbException {
|
|
||||||
ThreadItemList<I> items = new ThreadItemListImpl<>();
|
|
||||||
for (H h : headers) {
|
|
||||||
items.add(buildItem(h, textCache.get(h.getId())));
|
|
||||||
}
|
|
||||||
MessageId msgId = messageTracker.loadStoredMessageId(groupId);
|
|
||||||
if (LOG.isLoggable(INFO))
|
|
||||||
LOG.info("Loaded last top visible message id " + msgId);
|
|
||||||
items.setFirstVisibleId(msgId);
|
|
||||||
return items;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract I buildItem(H header, String text);
|
protected abstract I buildItem(H header, String text);
|
||||||
|
|
||||||
protected GroupId getGroupId() {
|
protected GroupId getGroupId() {
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import android.app.Application;
|
|||||||
|
|
||||||
import org.briarproject.bramble.api.crypto.CryptoExecutor;
|
import org.briarproject.bramble.api.crypto.CryptoExecutor;
|
||||||
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
||||||
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
|
import org.briarproject.bramble.api.db.Transaction;
|
||||||
import org.briarproject.bramble.api.db.TransactionManager;
|
import org.briarproject.bramble.api.db.TransactionManager;
|
||||||
import org.briarproject.bramble.api.event.EventBus;
|
import org.briarproject.bramble.api.event.EventBus;
|
||||||
import org.briarproject.bramble.api.event.EventListener;
|
import org.briarproject.bramble.api.event.EventListener;
|
||||||
@@ -12,34 +14,51 @@ import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
|||||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||||
import org.briarproject.bramble.api.sync.GroupId;
|
import org.briarproject.bramble.api.sync.GroupId;
|
||||||
|
import org.briarproject.bramble.api.sync.MessageId;
|
||||||
import org.briarproject.bramble.api.system.AndroidExecutor;
|
import org.briarproject.bramble.api.system.AndroidExecutor;
|
||||||
import org.briarproject.bramble.api.system.Clock;
|
import org.briarproject.bramble.api.system.Clock;
|
||||||
import org.briarproject.briar.android.viewmodel.DbViewModel;
|
import org.briarproject.briar.android.viewmodel.DbViewModel;
|
||||||
|
import org.briarproject.briar.android.viewmodel.LiveResult;
|
||||||
import org.briarproject.briar.api.android.AndroidNotificationManager;
|
import org.briarproject.briar.api.android.AndroidNotificationManager;
|
||||||
import org.briarproject.briar.api.client.NamedGroup;
|
import org.briarproject.briar.api.client.MessageTracker;
|
||||||
|
import org.briarproject.briar.api.client.PostHeader;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import androidx.annotation.CallSuper;
|
import androidx.annotation.CallSuper;
|
||||||
|
import androidx.annotation.UiThread;
|
||||||
|
import androidx.lifecycle.LiveData;
|
||||||
|
import androidx.lifecycle.MutableLiveData;
|
||||||
|
|
||||||
|
import static java.util.logging.Level.INFO;
|
||||||
import static java.util.logging.Logger.getLogger;
|
import static java.util.logging.Logger.getLogger;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logDuration;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.now;
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
public abstract class ThreadListViewModel<G extends NamedGroup, I extends ThreadItem>
|
public abstract class ThreadListViewModel<I extends ThreadItem> extends DbViewModel
|
||||||
extends DbViewModel implements EventListener {
|
implements EventListener {
|
||||||
|
|
||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
getLogger(ThreadListViewModel.class.getName());
|
getLogger(ThreadListViewModel.class.getName());
|
||||||
|
|
||||||
|
|
||||||
protected final IdentityManager identityManager;
|
protected final IdentityManager identityManager;
|
||||||
protected final AndroidNotificationManager notificationManager;
|
protected final AndroidNotificationManager notificationManager;
|
||||||
protected final Executor cryptoExecutor;
|
protected final Executor cryptoExecutor;
|
||||||
protected final Clock clock;
|
protected final Clock clock;
|
||||||
|
private final MessageTracker messageTracker;
|
||||||
private final EventBus eventBus;
|
private final EventBus eventBus;
|
||||||
|
|
||||||
|
private final Map<MessageId, String> textCache = new ConcurrentHashMap<>();
|
||||||
|
private final MutableLiveData<LiveResult<List<I>>> items =
|
||||||
|
new MutableLiveData<>();
|
||||||
|
|
||||||
protected volatile GroupId groupId;
|
protected volatile GroupId groupId;
|
||||||
|
|
||||||
public ThreadListViewModel(Application application,
|
public ThreadListViewModel(Application application,
|
||||||
@@ -51,12 +70,14 @@ public abstract class ThreadListViewModel<G extends NamedGroup, I extends Thread
|
|||||||
AndroidNotificationManager notificationManager,
|
AndroidNotificationManager notificationManager,
|
||||||
@CryptoExecutor Executor cryptoExecutor,
|
@CryptoExecutor Executor cryptoExecutor,
|
||||||
Clock clock,
|
Clock clock,
|
||||||
|
MessageTracker messageTracker,
|
||||||
EventBus eventBus) {
|
EventBus eventBus) {
|
||||||
super(application, dbExecutor, lifecycleManager, db, androidExecutor);
|
super(application, dbExecutor, lifecycleManager, db, androidExecutor);
|
||||||
this.identityManager = identityManager;
|
this.identityManager = identityManager;
|
||||||
this.notificationManager = notificationManager;
|
this.notificationManager = notificationManager;
|
||||||
this.cryptoExecutor = cryptoExecutor;
|
this.cryptoExecutor = cryptoExecutor;
|
||||||
this.clock = clock;
|
this.clock = clock;
|
||||||
|
this.messageTracker = messageTracker;
|
||||||
this.eventBus = eventBus;
|
this.eventBus = eventBus;
|
||||||
this.eventBus.addListener(this);
|
this.eventBus.addListener(this);
|
||||||
}
|
}
|
||||||
@@ -74,6 +95,52 @@ public abstract class ThreadListViewModel<G extends NamedGroup, I extends Thread
|
|||||||
@CallSuper
|
@CallSuper
|
||||||
public void setGroupId(GroupId groupId) {
|
public void setGroupId(GroupId groupId) {
|
||||||
this.groupId = groupId;
|
this.groupId = groupId;
|
||||||
|
loadItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void loadItems();
|
||||||
|
|
||||||
|
@UiThread
|
||||||
|
protected void setItems(LiveResult<List<I>> items) {
|
||||||
|
this.items.setValue(items);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DatabaseExecutor
|
||||||
|
protected <H extends PostHeader> List<I> buildItems(
|
||||||
|
Transaction txn, Collection<H> headers, ItemGetter<H, I> itemGetter)
|
||||||
|
throws DbException {
|
||||||
|
long start = now();
|
||||||
|
ThreadItemList<I> items = new ThreadItemListImpl<>();
|
||||||
|
for (H header : headers) {
|
||||||
|
MessageId id = header.getId();
|
||||||
|
String text = textCache.get(header.getId());
|
||||||
|
if (text == null) {
|
||||||
|
text = loadMessageText(txn, header);
|
||||||
|
textCache.put(id, text);
|
||||||
|
}
|
||||||
|
items.add(itemGetter.getItem(header, text));
|
||||||
|
}
|
||||||
|
logDuration(LOG, "Loading bodies and creating items", start);
|
||||||
|
|
||||||
|
MessageId msgId = messageTracker.loadStoredMessageId(txn, groupId);
|
||||||
|
if (LOG.isLoggable(INFO)) {
|
||||||
|
LOG.info("Loaded last top visible message id " + msgId);
|
||||||
|
}
|
||||||
|
// TODO store this elsewhere
|
||||||
|
items.setFirstVisibleId(msgId);
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
@DatabaseExecutor
|
||||||
|
protected abstract String loadMessageText(Transaction txn,
|
||||||
|
PostHeader header) throws DbException;
|
||||||
|
|
||||||
|
LiveData<LiveResult<List<I>>> getItems() {
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ItemGetter<H extends PostHeader, I> {
|
||||||
|
I getItem(H header, String text);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,11 +20,11 @@ class ThreadScrollListener<I extends ThreadItem>
|
|||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
getLogger(ThreadScrollListener.class.getName());
|
getLogger(ThreadScrollListener.class.getName());
|
||||||
|
|
||||||
private final ThreadListController<?, I> controller;
|
private final ThreadListController<I> controller;
|
||||||
private final UnreadMessageButton upButton, downButton;
|
private final UnreadMessageButton upButton, downButton;
|
||||||
|
|
||||||
ThreadScrollListener(ThreadItemAdapter<I> adapter,
|
ThreadScrollListener(ThreadItemAdapter<I> adapter,
|
||||||
ThreadListController<?, I> controller,
|
ThreadListController<I> controller,
|
||||||
UnreadMessageButton upButton,
|
UnreadMessageButton upButton,
|
||||||
UnreadMessageButton downButton) {
|
UnreadMessageButton downButton) {
|
||||||
super(adapter);
|
super(adapter);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
|||||||
import org.briarproject.bramble.api.sync.MessageId;
|
import org.briarproject.bramble.api.sync.MessageId;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Comparator;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
@@ -13,14 +13,15 @@ public interface MessageTree<T extends MessageTree.MessageNode> {
|
|||||||
|
|
||||||
void add(Collection<T> nodes);
|
void add(Collection<T> nodes);
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
void add(T node);
|
void add(T node);
|
||||||
|
|
||||||
void setComparator(Comparator<T> comparator);
|
@Deprecated
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
Collection<T> depthFirstOrder();
|
List<T> depthFirstOrder();
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
boolean contains(MessageId m);
|
boolean contains(MessageId m);
|
||||||
|
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
|
|||||||
@@ -30,9 +30,14 @@ public class MessageTreeImpl<T extends MessageTree.MessageNode>
|
|||||||
private final List<List<T>> unsortedLists = new ArrayList<>();
|
private final List<List<T>> unsortedLists = new ArrayList<>();
|
||||||
|
|
||||||
@SuppressWarnings("UseCompareMethod")
|
@SuppressWarnings("UseCompareMethod")
|
||||||
private Comparator<T> comparator = (o1, o2) ->
|
private final Comparator<T> comparator = (o1, o2) ->
|
||||||
Long.valueOf(o1.getTimestamp()).compareTo(o2.getTimestamp());
|
Long.valueOf(o1.getTimestamp()).compareTo(o2.getTimestamp());
|
||||||
|
|
||||||
|
public MessageTreeImpl(Collection<T> collection) {
|
||||||
|
super();
|
||||||
|
add(collection);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void clear() {
|
public synchronized void clear() {
|
||||||
roots.clear();
|
roots.clear();
|
||||||
@@ -79,6 +84,7 @@ public class MessageTreeImpl<T extends MessageTree.MessageNode>
|
|||||||
@GuardedBy("this")
|
@GuardedBy("this")
|
||||||
private void sortUnsorted() {
|
private void sortUnsorted() {
|
||||||
for (List<T> list : unsortedLists) {
|
for (List<T> list : unsortedLists) {
|
||||||
|
//noinspection Java8ListSort
|
||||||
Collections.sort(list, comparator);
|
Collections.sort(list, comparator);
|
||||||
}
|
}
|
||||||
unsortedLists.clear();
|
unsortedLists.clear();
|
||||||
@@ -95,17 +101,7 @@ public class MessageTreeImpl<T extends MessageTree.MessageNode>
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void setComparator(Comparator<T> comparator) {
|
public synchronized List<T> depthFirstOrder() {
|
||||||
this.comparator = comparator;
|
|
||||||
// Sort all lists with the new comparator
|
|
||||||
Collections.sort(roots, comparator);
|
|
||||||
for (Map.Entry<MessageId, List<T>> entry : nodeMap.entrySet()) {
|
|
||||||
Collections.sort(entry.getValue(), comparator);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized Collection<T> depthFirstOrder() {
|
|
||||||
List<T> orderedList = new ArrayList<>();
|
List<T> orderedList = new ArrayList<>();
|
||||||
for (T root : roots) {
|
for (T root : roots) {
|
||||||
traverse(orderedList, root, 0);
|
traverse(orderedList, root, 0);
|
||||||
|
|||||||
Reference in New Issue
Block a user