Rework how ConversationFragment RecyclerView responds to data updates.

This commit is contained in:
Alex Hart 2020-06-07 16:25:21 -03:00 committed by Greyson Parrelli
parent 3a479d7eef
commit 7d06e2395f
11 changed files with 151 additions and 72 deletions

View File

@ -56,8 +56,8 @@ public class MainNavigator {
return false; return false;
} }
public void goToConversation(@NonNull RecipientId recipientId, long threadId, int distributionType, int startingPosition, boolean highlightStartPosition) { public void goToConversation(@NonNull RecipientId recipientId, long threadId, int distributionType, int startingPosition) {
Intent intent = ConversationActivity.buildIntent(activity, recipientId, threadId, distributionType, startingPosition, highlightStartPosition); Intent intent = ConversationActivity.buildIntent(activity, recipientId, threadId, distributionType, startingPosition);
activity.startActivity(intent); activity.startActivity(intent);
activity.overridePendingTransition(R.anim.slide_from_end, R.anim.fade_scale_out); activity.overridePendingTransition(R.anim.slide_from_end, R.anim.fade_scale_out);

View File

@ -289,7 +289,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
public static final String STICKER_EXTRA = "sticker_extra"; public static final String STICKER_EXTRA = "sticker_extra";
public static final String DISTRIBUTION_TYPE_EXTRA = "distribution_type"; public static final String DISTRIBUTION_TYPE_EXTRA = "distribution_type";
public static final String STARTING_POSITION_EXTRA = "starting_position"; public static final String STARTING_POSITION_EXTRA = "starting_position";
public static final String HIGHLIGHT_STARTING_POSITION_EXTRA = "highlight_starting_position";
private static final int PICK_GALLERY = 1; private static final int PICK_GALLERY = 1;
private static final int PICK_DOCUMENT = 2; private static final int PICK_DOCUMENT = 2;
@ -358,15 +357,13 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
@NonNull RecipientId recipientId, @NonNull RecipientId recipientId,
long threadId, long threadId,
int distributionType, int distributionType,
int startingPosition, int startingPosition)
boolean highlightStartingPosition)
{ {
Intent intent = new Intent(context, ConversationActivity.class); Intent intent = new Intent(context, ConversationActivity.class);
intent.putExtra(ConversationActivity.RECIPIENT_EXTRA, recipientId); intent.putExtra(ConversationActivity.RECIPIENT_EXTRA, recipientId);
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, threadId); intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, threadId);
intent.putExtra(ConversationActivity.DISTRIBUTION_TYPE_EXTRA, distributionType); intent.putExtra(ConversationActivity.DISTRIBUTION_TYPE_EXTRA, distributionType);
intent.putExtra(ConversationActivity.STARTING_POSITION_EXTRA, startingPosition); intent.putExtra(ConversationActivity.STARTING_POSITION_EXTRA, startingPosition);
intent.putExtra(ConversationActivity.HIGHLIGHT_STARTING_POSITION_EXTRA, highlightStartingPosition);
return intent; return intent;
} }

View File

@ -100,7 +100,6 @@ public class ConversationAdapter<V extends View & BindableConversationItem>
private View headerView; private View headerView;
private View footerView; private View footerView;
ConversationAdapter(@NonNull GlideRequests glideRequests, ConversationAdapter(@NonNull GlideRequests glideRequests,
@NonNull Locale locale, @NonNull Locale locale,
@Nullable ItemClickListener clickListener, @Nullable ItemClickListener clickListener,
@ -248,7 +247,7 @@ public class ConversationAdapter<V extends View & BindableConversationItem>
@Override @Override
public void submitList(@Nullable PagedList<MessageRecord> pagedList) { public void submitList(@Nullable PagedList<MessageRecord> pagedList) {
cleanFastRecords(); cleanFastRecords();
super.submitList(pagedList, this::notifyDataSetChanged); super.submitList(pagedList);
} }
@Override @Override
@ -341,15 +340,35 @@ public class ConversationAdapter<V extends View & BindableConversationItem>
/** /**
* Sets the view the appears at the top of the list (because the list is reversed). * Sets the view the appears at the top of the list (because the list is reversed).
*/ */
void setFooterView(View view) { void setFooterView(@Nullable View view) {
boolean hadFooter = hasFooter();
this.footerView = view; this.footerView = view;
if (view == null && hadFooter) {
notifyItemRemoved(getItemCount());
} else if (view != null && hadFooter) {
notifyItemChanged(getItemCount() - 1);
} else if (view != null) {
notifyItemInserted(getItemCount() - 1);
}
} }
/** /**
* Sets the view that appears at the bottom of the list (because the list is reversed). * Sets the view that appears at the bottom of the list (because the list is reversed).
*/ */
void setHeaderView(View view) { void setHeaderView(@Nullable View view) {
boolean hadHeader = hasHeader();
this.headerView = view; this.headerView = view;
if (view == null && hadHeader) {
notifyItemRemoved(0);
} else if (view != null && hadHeader) {
notifyItemChanged(0);
} else if (view != null) {
notifyItemInserted(0);
}
} }
/** /**

View File

@ -4,6 +4,7 @@ package org.thoughtcrime.securesms.conversation;
* Represents metadata about a conversation. * Represents metadata about a conversation.
*/ */
final class ConversationData { final class ConversationData {
private final long threadId;
private final long lastSeen; private final long lastSeen;
private final int lastSeenPosition; private final int lastSeenPosition;
private final boolean hasSent; private final boolean hasSent;
@ -11,13 +12,15 @@ final class ConversationData {
private final boolean hasPreMessageRequestMessages; private final boolean hasPreMessageRequestMessages;
private final int jumpToPosition; private final int jumpToPosition;
ConversationData(long lastSeen, ConversationData(long threadId,
long lastSeen,
int lastSeenPosition, int lastSeenPosition,
boolean hasSent, boolean hasSent,
boolean isMessageRequestAccepted, boolean isMessageRequestAccepted,
boolean hasPreMessageRequestMessages, boolean hasPreMessageRequestMessages,
int jumpToPosition) int jumpToPosition)
{ {
this.threadId = threadId;
this.lastSeen = lastSeen; this.lastSeen = lastSeen;
this.lastSeenPosition = lastSeenPosition; this.lastSeenPosition = lastSeenPosition;
this.hasSent = hasSent; this.hasSent = hasSent;
@ -26,6 +29,10 @@ final class ConversationData {
this.jumpToPosition = jumpToPosition; this.jumpToPosition = jumpToPosition;
} }
public long getThreadId() {
return threadId;
}
long getLastSeen() { long getLastSeen() {
return lastSeen; return lastSeen;
} }

View File

@ -103,7 +103,10 @@ class ConversationDataSource extends PositionalDataSource<MessageRecord> {
} }
callback.onResult(records); callback.onResult(records);
if (!isInvalid()) {
Util.runOnMain(dataUpdateCallback::onDataUpdated); Util.runOnMain(dataUpdateCallback::onDataUpdated);
}
Log.d(TAG, "[Update] " + (System.currentTimeMillis() - start) + " ms" + (isInvalid() ? " -- invalidated" : "")); Log.d(TAG, "[Update] " + (System.currentTimeMillis() - start) + " ms" + (isInvalid() ? " -- invalidated" : ""));
} }

View File

@ -21,6 +21,7 @@ import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.graphics.Rect;
import android.net.Uri; import android.net.Uri;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Build; import android.os.Build;
@ -63,9 +64,6 @@ import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.MessageDetailsActivity; import org.thoughtcrime.securesms.MessageDetailsActivity;
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity; import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity;
import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.groups.GroupId;
import org.thoughtcrime.securesms.recipients.ui.bottomsheet.RecipientBottomSheetDialogFragment;
import org.thoughtcrime.securesms.sharing.ShareActivity;
import org.thoughtcrime.securesms.attachments.Attachment; import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.components.ConversationTypingView; import org.thoughtcrime.securesms.components.ConversationTypingView;
import org.thoughtcrime.securesms.components.TooltipPopup; import org.thoughtcrime.securesms.components.TooltipPopup;
@ -73,8 +71,8 @@ import org.thoughtcrime.securesms.components.recyclerview.SmoothScrollingLinearL
import org.thoughtcrime.securesms.contactshare.Contact; import org.thoughtcrime.securesms.contactshare.Contact;
import org.thoughtcrime.securesms.contactshare.ContactUtil; import org.thoughtcrime.securesms.contactshare.ContactUtil;
import org.thoughtcrime.securesms.contactshare.SharedContactDetailsActivity; import org.thoughtcrime.securesms.contactshare.SharedContactDetailsActivity;
import org.thoughtcrime.securesms.conversation.ConversationAdapter.StickyHeaderViewHolder;
import org.thoughtcrime.securesms.conversation.ConversationAdapter.ItemClickListener; import org.thoughtcrime.securesms.conversation.ConversationAdapter.ItemClickListener;
import org.thoughtcrime.securesms.conversation.ConversationAdapter.StickyHeaderViewHolder;
import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MessagingDatabase; import org.thoughtcrime.securesms.database.MessagingDatabase;
import org.thoughtcrime.securesms.database.MmsSmsDatabase; import org.thoughtcrime.securesms.database.MmsSmsDatabase;
@ -83,6 +81,7 @@ import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord;
import org.thoughtcrime.securesms.database.model.MessageRecord; import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.database.model.MmsMessageRecord; import org.thoughtcrime.securesms.database.model.MmsMessageRecord;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.groups.GroupId;
import org.thoughtcrime.securesms.jobs.DirectoryRefreshJob; import org.thoughtcrime.securesms.jobs.DirectoryRefreshJob;
import org.thoughtcrime.securesms.jobs.MultiDeviceViewOnceOpenJob; import org.thoughtcrime.securesms.jobs.MultiDeviceViewOnceOpenJob;
import org.thoughtcrime.securesms.linkpreview.LinkPreview; import org.thoughtcrime.securesms.linkpreview.LinkPreview;
@ -100,8 +99,10 @@ import org.thoughtcrime.securesms.reactions.ReactionsBottomSheetDialogFragment;
import org.thoughtcrime.securesms.recipients.LiveRecipient; import org.thoughtcrime.securesms.recipients.LiveRecipient;
import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.recipients.ui.bottomsheet.RecipientBottomSheetDialogFragment;
import org.thoughtcrime.securesms.revealable.ViewOnceMessageActivity; import org.thoughtcrime.securesms.revealable.ViewOnceMessageActivity;
import org.thoughtcrime.securesms.revealable.ViewOnceUtil; import org.thoughtcrime.securesms.revealable.ViewOnceUtil;
import org.thoughtcrime.securesms.sharing.ShareActivity;
import org.thoughtcrime.securesms.sms.MessageSender; import org.thoughtcrime.securesms.sms.MessageSender;
import org.thoughtcrime.securesms.sms.OutgoingTextMessage; import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
import org.thoughtcrime.securesms.stickers.StickerLocator; import org.thoughtcrime.securesms.stickers.StickerLocator;
@ -163,6 +164,8 @@ public class ConversationFragment extends Fragment {
private MessageRequestViewModel messageRequestViewModel; private MessageRequestViewModel messageRequestViewModel;
private ConversationViewModel conversationViewModel; private ConversationViewModel conversationViewModel;
private Deferred deferred = new Deferred();
public static void prepare(@NonNull Context context) { public static void prepare(@NonNull Context context) {
FrameLayout parent = new FrameLayout(context); FrameLayout parent = new FrameLayout(context);
parent.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT)); parent.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT));
@ -221,7 +224,7 @@ public class ConversationFragment extends Fragment {
getListAdapter().submitList(list); getListAdapter().submitList(list);
} }
}); });
conversationViewModel.getConversationMetadata().observe(this, this::presentConversationMetadata); conversationViewModel.getConversationMetadata().observe(this, data -> deferred.defer(() -> presentConversationMetadata(data)));
return view; return view;
} }
@ -279,16 +282,6 @@ public class ConversationFragment extends Fragment {
initializeTypingObserver(); initializeTypingObserver();
} }
@Override
public void onResume() {
super.onResume();
if (list.getAdapter() != null) {
Log.i(TAG, "onResume notifyDataSetChanged");
list.getAdapter().notifyDataSetChanged();
}
}
@Override @Override
public void onStop() { public void onStop() {
super.onStop(); super.onStop();
@ -411,6 +404,7 @@ public class ConversationFragment extends Fragment {
this.threadId = this.getActivity().getIntent().getLongExtra(ConversationActivity.THREAD_ID_EXTRA, -1); this.threadId = this.getActivity().getIntent().getLongExtra(ConversationActivity.THREAD_ID_EXTRA, -1);
this.unknownSenderView = new UnknownSenderView(getActivity(), recipient.get(), threadId, () -> clearHeaderIfNotTyping(getListAdapter())); this.unknownSenderView = new UnknownSenderView(getActivity(), recipient.get(), threadId, () -> clearHeaderIfNotTyping(getListAdapter()));
deferred.setDeferred(true);
conversationViewModel.onConversationDataAvailable(threadId, startingPosition); conversationViewModel.onConversationDataAvailable(threadId, startingPosition);
OnScrollListener scrollListener = new ConversationScrollListener(getActivity()); OnScrollListener scrollListener = new ConversationScrollListener(getActivity());
@ -429,6 +423,8 @@ public class ConversationFragment extends Fragment {
list.addItemDecoration(new StickyHeaderDecoration(adapter, false, false)); list.addItemDecoration(new StickyHeaderDecoration(adapter, false, false));
ConversationAdapter.initializePool(list.getRecycledViewPool()); ConversationAdapter.initializePool(list.getRecycledViewPool());
adapter.registerAdapterDataObserver(new DataObserver());
setLastSeen(conversationViewModel.getLastSeen()); setLastSeen(conversationViewModel.getLastSeen());
emptyConversationBanner.setVisibility(View.GONE); emptyConversationBanner.setVisibility(View.GONE);
@ -482,14 +478,11 @@ public class ConversationFragment extends Fragment {
}); });
list.postDelayed(() -> list.setVerticalScrollBarEnabled(true), 300); list.postDelayed(() -> list.setVerticalScrollBarEnabled(true), 300);
adapter.setHeaderView(typingView); adapter.setHeaderView(typingView);
adapter.notifyItemInserted(0);
} else { } else {
if (isTypingIndicatorShowing()) { if (isTypingIndicatorShowing()) {
adapter.setHeaderView(typingView); adapter.setHeaderView(typingView);
adapter.notifyItemChanged(0);
} else { } else {
adapter.setHeaderView(typingView); adapter.setHeaderView(typingView);
adapter.notifyItemInserted(0);
} }
} }
} else { } else {
@ -500,12 +493,10 @@ public class ConversationFragment extends Fragment {
list.setVerticalScrollBarEnabled(false); list.setVerticalScrollBarEnabled(false);
list.postDelayed(() -> { list.postDelayed(() -> {
adapter.setHeaderView(null); adapter.setHeaderView(null);
adapter.notifyItemRemoved(0);
list.post(() -> list.setVerticalScrollBarEnabled(true)); list.post(() -> list.setVerticalScrollBarEnabled(true));
}, 200); }, 200);
} else if (!replacedByIncomingMessage) { } else if (!replacedByIncomingMessage) {
adapter.setHeaderView(null); adapter.setHeaderView(null);
adapter.notifyItemRemoved(0);
} else { } else {
adapter.setHeaderView(null); adapter.setHeaderView(null);
} }
@ -552,6 +543,8 @@ public class ConversationFragment extends Fragment {
if (this.threadId != threadId) { if (this.threadId != threadId) {
this.threadId = threadId; this.threadId = threadId;
messageRequestViewModel.setConversationInfo(recipient.getId(), threadId); messageRequestViewModel.setConversationInfo(recipient.getId(), threadId);
deferred.setDeferred(true);
conversationViewModel.onConversationDataAvailable(threadId, -1); conversationViewModel.onConversationDataAvailable(threadId, -1);
initializeListAdapter(); initializeListAdapter();
} }
@ -866,8 +859,6 @@ public class ConversationFragment extends Fragment {
} }
private void presentConversationMetadata(@NonNull ConversationData conversation) { private void presentConversationMetadata(@NonNull ConversationData conversation) {
Log.d(TAG, "presentConversationMetadata()");
ConversationAdapter adapter = getListAdapter(); ConversationAdapter adapter = getListAdapter();
if (adapter == null) { if (adapter == null) {
return; return;
@ -907,17 +898,10 @@ public class ConversationFragment extends Fragment {
private void scrollToStartingPosition(int startingPosition) { private void scrollToStartingPosition(int startingPosition) {
list.post(() -> { list.post(() -> {
list.getLayoutManager().scrollToPosition(startingPosition); list.getLayoutManager().scrollToPosition(startingPosition);
if (shouldHighlightStartingPosition()) {
getListAdapter().pulseHighlightItem(startingPosition); getListAdapter().pulseHighlightItem(startingPosition);
}
}); });
} }
private boolean shouldHighlightStartingPosition() {
return requireActivity().getIntent().getBooleanExtra(ConversationActivity.HIGHLIGHT_STARTING_POSITION_EXTRA, false);
}
private void scrollToLastSeenPosition(int lastSeenPosition) { private void scrollToLastSeenPosition(int lastSeenPosition) {
if (lastSeenPosition > 0) { if (lastSeenPosition > 0) {
list.post(() -> getListLayoutManager().scrollToPositionWithOffset(lastSeenPosition, list.getHeight())); list.post(() -> getListLayoutManager().scrollToPositionWithOffset(lastSeenPosition, list.getHeight()));
@ -1072,6 +1056,44 @@ public class ConversationFragment extends Fragment {
} }
} }
private class DataObserver extends RecyclerView.AdapterDataObserver {
private final Rect rect = new Rect();
@Override
public void onItemRangeInserted(int positionStart, int itemCount) {
if (deferred.isDeferred()) {
deferred.setDeferred(false);
return;
}
if (positionStart == 0 && itemCount == 1 && isTypingIndicatorShowing()) {
return;
}
if (list.getScrollState() == RecyclerView.SCROLL_STATE_IDLE) {
int firstVisibleItem = getListLayoutManager().findFirstVisibleItemPosition();
if (firstVisibleItem == 0) {
View view = getListLayoutManager().findViewByPosition(0);
if (view == null) {
return;
}
view.getDrawingRect(rect);
list.offsetDescendantRectToMyCoords(view, rect);
int bottom = rect.bottom;
list.getDrawingRect(rect);
if (bottom <= rect.bottom) {
getListLayoutManager().scrollToPosition(0);
}
}
}
}
}
private class ConversationFragmentItemClickListener implements ItemClickListener { private class ConversationFragmentItemClickListener implements ItemClickListener {
@Override @Override
@ -1424,4 +1446,34 @@ public class ConversationFragment extends Fragment {
}, 400); }, 400);
} }
} }
private static class Deferred {
private Runnable deferred;
private boolean isDeferred;
public void defer(@Nullable Runnable deferred) {
this.deferred = deferred;
executeIfNecessary();
}
public void setDeferred(boolean isDeferred) {
this.isDeferred = isDeferred;
executeIfNecessary();
}
public boolean isDeferred() {
return isDeferred;
}
private void executeIfNecessary() {
if (deferred != null && !isDeferred) {
Runnable local = deferred;
deferred = null;
local.run();
}
}
}
} }

View File

@ -52,6 +52,6 @@ class ConversationRepository {
lastSeen = 0; lastSeen = 0;
} }
return new ConversationData(lastSeen, lastSeenPosition, hasSent, isMessageRequestAccepted, hasPreMessageRequestMessages, jumpToPosition); return new ConversationData(threadId, lastSeen, lastSeenPosition, hasSent, isMessageRequestAccepted, hasPreMessageRequestMessages, jumpToPosition);
} }
} }

View File

@ -54,17 +54,30 @@ class ConversationViewModel extends ViewModel {
this.onNextMessageLoad = new CopyOnWriteArrayList<>(); this.onNextMessageLoad = new CopyOnWriteArrayList<>();
this.invalidator = new Invalidator(); this.invalidator = new Invalidator();
LiveData<Pair<Long, PagedList<MessageRecord>>> messagesForThreadId = Transformations.switchMap(threadId, thread -> { LiveData<ConversationData> conversationDataForRequestedThreadId = Transformations.switchMap(threadId, thread -> {
DataSource.Factory<Integer, MessageRecord> factory = new ConversationDataSource.Factory(context, thread, invalidator, this::onMessagesUpdated); return conversationRepository.getConversationData(thread, jumpToPosition);
});
LiveData<Pair<Long, PagedList<MessageRecord>>> messagesForThreadId = Transformations.switchMap(conversationDataForRequestedThreadId, data -> {
DataSource.Factory<Integer, MessageRecord> factory = new ConversationDataSource.Factory(context, data.getThreadId(), invalidator, this::onMessagesUpdated);
PagedList.Config config = new PagedList.Config.Builder() PagedList.Config config = new PagedList.Config.Builder()
.setPageSize(25) .setPageSize(25)
.setInitialLoadSizeHint(25) .setInitialLoadSizeHint(25)
.build(); .build();
final int startPosition;
if (jumpToPosition > 0) {
startPosition = jumpToPosition;
} else {
startPosition = data.getLastSeenPosition();
}
Log.d(TAG, "Starting at position " + startPosition + " :: " + jumpToPosition + " :: " + data.getLastSeenPosition());
return Transformations.map(new LivePagedListBuilder<>(factory, config).setFetchExecutor(ConversationDataSource.EXECUTOR) return Transformations.map(new LivePagedListBuilder<>(factory, config).setFetchExecutor(ConversationDataSource.EXECUTOR)
.setInitialLoadKey(Math.max(jumpToPosition, 0)) .setInitialLoadKey(Math.max(startPosition, 0))
.build(), .build(),
input -> new Pair<>(thread, input)); input -> new Pair<>(data.getThreadId(), input));
}); });
this.messages = Transformations.map(messagesForThreadId, Pair::second); this.messages = Transformations.map(messagesForThreadId, Pair::second);

View File

@ -353,24 +353,19 @@ public class ConversationListFragment extends MainFragment implements LoaderMana
getNavigator().goToConversation(threadRecord.getRecipient().getId(), getNavigator().goToConversation(threadRecord.getRecipient().getId(),
threadRecord.getThreadId(), threadRecord.getThreadId(),
threadRecord.getDistributionType(), threadRecord.getDistributionType(),
threadRecord.getUnreadCount(), -1);
false);
} }
@Override @Override
public void onContactClicked(@NonNull Recipient contact) { public void onContactClicked(@NonNull Recipient contact) {
SimpleTask.run(getViewLifecycleOwner().getLifecycle(), () -> { SimpleTask.run(getViewLifecycleOwner().getLifecycle(), () -> {
long threadId = DatabaseFactory.getThreadDatabase(getContext()).getThreadIdIfExistsFor(contact); return DatabaseFactory.getThreadDatabase(getContext()).getThreadIdIfExistsFor(contact);
int unreadCount = DatabaseFactory.getMmsSmsDatabase(getContext()).getUnreadCount(threadId); }, threadId -> {
return new Pair<>(threadId, unreadCount);
}, pair -> {
hideKeyboard(); hideKeyboard();
getNavigator().goToConversation(contact.getId(), getNavigator().goToConversation(contact.getId(),
pair.first(), threadId,
ThreadDatabase.DistributionTypes.DEFAULT, ThreadDatabase.DistributionTypes.DEFAULT,
pair.second(), -1);
false);
}); });
} }
@ -384,8 +379,7 @@ public class ConversationListFragment extends MainFragment implements LoaderMana
getNavigator().goToConversation(message.conversationRecipient.getId(), getNavigator().goToConversation(message.conversationRecipient.getId(),
message.threadId, message.threadId,
ThreadDatabase.DistributionTypes.DEFAULT, ThreadDatabase.DistributionTypes.DEFAULT,
startingPosition, startingPosition);
true);
}); });
} }
@ -735,8 +729,8 @@ public class ConversationListFragment extends MainFragment implements LoaderMana
actionMode.setTitle(String.valueOf(defaultAdapter.getBatchSelectionIds().size())); actionMode.setTitle(String.valueOf(defaultAdapter.getBatchSelectionIds().size()));
} }
private void handleCreateConversation(long threadId, Recipient recipient, int distributionType, int unreadCount) { private void handleCreateConversation(long threadId, Recipient recipient, int distributionType) {
getNavigator().goToConversation(recipient.getId(), threadId, distributionType, unreadCount, false); getNavigator().goToConversation(recipient.getId(), threadId, distributionType, -1);
} }
@Override @Override
@ -770,7 +764,7 @@ public class ConversationListFragment extends MainFragment implements LoaderMana
@Override @Override
public void onItemClick(ConversationListItem item) { public void onItemClick(ConversationListItem item) {
if (actionMode == null) { if (actionMode == null) {
handleCreateConversation(item.getThreadId(), item.getRecipient(), item.getDistributionType(), item.getUnreadCount()); handleCreateConversation(item.getThreadId(), item.getRecipient(), item.getDistributionType());
} else { } else {
ConversationListAdapter adapter = (ConversationListAdapter)list.getAdapter(); ConversationListAdapter adapter = (ConversationListAdapter)list.getAdapter();
adapter.toggleThreadInBatchSet(item.getThread()); adapter.toggleThreadInBatchSet(item.getThread());

View File

@ -63,8 +63,7 @@ public class AddGroupDetailsActivity extends PassphraseRequiredActionBarActivity
recipientId, recipientId,
threadId, threadId,
ThreadDatabase.DistributionTypes.DEFAULT, ThreadDatabase.DistributionTypes.DEFAULT,
-1, -1);
false);
startActivity(intent); startActivity(intent);
setResult(RESULT_OK); setResult(RESULT_OK);

View File

@ -81,12 +81,7 @@ public class NotificationItem {
Recipient recipient = threadRecipient != null ? threadRecipient : conversationRecipient; Recipient recipient = threadRecipient != null ? threadRecipient : conversationRecipient;
int startingPosition = jumpToMessage ? getStartingPosition(context, threadId, messageReceivedTimestamp) : -1; int startingPosition = jumpToMessage ? getStartingPosition(context, threadId, messageReceivedTimestamp) : -1;
if (!jumpToMessage) { Intent intent = ConversationActivity.buildIntent(context, recipient.getId(), threadId, 0, startingPosition);
int unreadCount = DatabaseFactory.getMmsSmsDatabase(context).getUnreadCount(threadId);
startingPosition = unreadCount > 0 ? unreadCount : -1;
}
Intent intent = ConversationActivity.buildIntent(context, recipient.getId(), threadId, 0, startingPosition, jumpToMessage);
makeIntentUniqueToPreventMerging(intent); makeIntentUniqueToPreventMerging(intent);