Fix jumping to last seen position.

This commit is contained in:
Greyson Parrelli 2020-05-11 11:47:30 -04:00 committed by Alex Hart
parent 1778c1ef7d
commit 53d122ed55
10 changed files with 81 additions and 89 deletions

View file

@ -55,8 +55,8 @@ public class MainNavigator {
return false; return false;
} }
public void goToConversation(@NonNull RecipientId recipientId, long threadId, int distributionType, long lastSeen, int startingPosition) { public void goToConversation(@NonNull RecipientId recipientId, long threadId, int distributionType, int startingPosition) {
Intent intent = ConversationActivity.buildIntent(activity, recipientId, threadId, distributionType, lastSeen, startingPosition); 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

@ -281,12 +281,10 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
public static final String RECIPIENT_EXTRA = "recipient_id"; public static final String RECIPIENT_EXTRA = "recipient_id";
public static final String THREAD_ID_EXTRA = "thread_id"; public static final String THREAD_ID_EXTRA = "thread_id";
public static final String IS_ARCHIVED_EXTRA = "is_archived";
public static final String TEXT_EXTRA = "draft_text"; public static final String TEXT_EXTRA = "draft_text";
public static final String MEDIA_EXTRA = "media_list"; public static final String MEDIA_EXTRA = "media_list";
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 LAST_SEEN_EXTRA = "last_seen";
public static final String STARTING_POSITION_EXTRA = "starting_position"; public static final String STARTING_POSITION_EXTRA = "starting_position";
private static final int PICK_GALLERY = 1; private static final int PICK_GALLERY = 1;
@ -342,12 +340,10 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
private LiveRecipient recipient; private LiveRecipient recipient;
private long threadId; private long threadId;
private int distributionType; private int distributionType;
private boolean archived;
private boolean isSecureText; private boolean isSecureText;
private boolean isDefaultSms = true; private boolean isDefaultSms = true;
private boolean isMmsEnabled = true; private boolean isMmsEnabled = true;
private boolean isSecurityInitialized = false; private boolean isSecurityInitialized = false;
private boolean shouldDisplayMessageRequestUi = true;
private final IdentityRecordList identityRecords = new IdentityRecordList(); private final IdentityRecordList identityRecords = new IdentityRecordList();
private final DynamicTheme dynamicTheme = new DynamicDarkToolbarTheme(); private final DynamicTheme dynamicTheme = new DynamicDarkToolbarTheme();
@ -357,14 +353,12 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
@NonNull RecipientId recipientId, @NonNull RecipientId recipientId,
long threadId, long threadId,
int distributionType, int distributionType,
long lastSeen,
int startingPosition) int startingPosition)
{ {
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.LAST_SEEN_EXTRA, lastSeen);
intent.putExtra(ConversationActivity.STARTING_POSITION_EXTRA, startingPosition); intent.putExtra(ConversationActivity.STARTING_POSITION_EXTRA, startingPosition);
return intent; return intent;
@ -1739,7 +1733,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
recipient = Recipient.live(getIntent().getParcelableExtra(RECIPIENT_EXTRA)); recipient = Recipient.live(getIntent().getParcelableExtra(RECIPIENT_EXTRA));
threadId = getIntent().getLongExtra(THREAD_ID_EXTRA, -1); threadId = getIntent().getLongExtra(THREAD_ID_EXTRA, -1);
archived = getIntent().getBooleanExtra(IS_ARCHIVED_EXTRA, false);
distributionType = getIntent().getIntExtra(DISTRIBUTION_TYPE_EXTRA, ThreadDatabase.DistributionTypes.DEFAULT); distributionType = getIntent().getIntExtra(DISTRIBUTION_TYPE_EXTRA, ThreadDatabase.DistributionTypes.DEFAULT);
glideRequests = GlideApp.with(this); glideRequests = GlideApp.with(this);

View file

@ -24,6 +24,7 @@ import android.widget.TextView;
import androidx.annotation.AnyThread; import androidx.annotation.AnyThread;
import androidx.annotation.LayoutRes; import androidx.annotation.LayoutRes;
import androidx.annotation.MainThread;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.paging.PagedList; import androidx.paging.PagedList;
@ -241,16 +242,17 @@ 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); super.submitList(pagedList, this::notifyDataSetChanged);
notifyDataSetChanged();
} }
@Override @Override
protected @Nullable MessageRecord getItem(int position) { protected @Nullable MessageRecord getItem(int position) {
position = hasHeader() ? position - 1 : position;
if (position < fastRecords.size()) { if (position < fastRecords.size()) {
return fastRecords.get(position); return fastRecords.get(position);
} else { } else {
int correctedPosition = position - fastRecords.size() - (hasHeader() ? 1 : 0); int correctedPosition = position - fastRecords.size();
return super.getItem(correctedPosition); return super.getItem(correctedPosition);
} }
} }
@ -302,31 +304,19 @@ public class ConversationAdapter<V extends View & BindableConversationItem>
} }
/** /**
* Given a timestamp, this will return the position in the adapter of the message with the * The presence of a header may throw off the position you'd like to jump to. This will return
* nearest received timestamp, or -1 if none is found. * an adjusted message position based on adapter state.
*/ */
int findLastSeenPosition(long lastSeen) { @MainThread
if (lastSeen <= 0) { int getAdapterPositionForMessagePosition(int messagePosition) {
return -1; return hasHeader() ? messagePosition + 1 : messagePosition;
}
int count = getItemCount() - (hasFooter() ? 1 : 0);
for (int i = (hasHeader() ? 1 : 0); i < count; i++) {
MessageRecord messageRecord = getItem(i);
if (messageRecord == null || messageRecord.isOutgoing() || messageRecord.getDateReceived() <= lastSeen) {
return i;
}
}
return -1;
} }
/** /**
* Finds the received timestamp for the item at the requested adapter position. Will return 0 if * Finds the received timestamp for the item at the requested adapter position. Will return 0 if
* the position doesn't refer to an incoming message. * the position doesn't refer to an incoming message.
*/ */
@MainThread
long getReceivedTimestamp(int position) { long getReceivedTimestamp(int position) {
if (isHeaderPosition(position)) return 0; if (isHeaderPosition(position)) return 0;
if (isFooterPosition(position)) return 0; if (isFooterPosition(position)) return 0;
@ -385,8 +375,9 @@ public class ConversationAdapter<V extends View & BindableConversationItem>
* Adds a record to a memory cache to allow it to be rendered immediately, as opposed to waiting * Adds a record to a memory cache to allow it to be rendered immediately, as opposed to waiting
* for a database change. * for a database change.
*/ */
@MainThread
void addFastRecord(MessageRecord record) { void addFastRecord(MessageRecord record) {
fastRecords.add(record); fastRecords.add(0, record);
notifyDataSetChanged(); notifyDataSetChanged();
} }
@ -426,6 +417,7 @@ public class ConversationAdapter<V extends View & BindableConversationItem>
} }
} }
@MainThread
private void cleanFastRecords() { private void cleanFastRecords() {
synchronized (releasedFastRecords) { synchronized (releasedFastRecords) {
Iterator<MessageRecord> recordIterator = fastRecords.iterator(); Iterator<MessageRecord> recordIterator = fastRecords.iterator();

View file

@ -5,18 +5,21 @@ package org.thoughtcrime.securesms.conversation;
*/ */
final class ConversationData { final class ConversationData {
private final long lastSeen; private final long lastSeen;
private final int lastSeenPosition;
private final boolean hasSent; private final boolean hasSent;
private final boolean isMessageRequestAccepted; private final boolean isMessageRequestAccepted;
private final boolean hasPreMessageRequestMessages; private final boolean hasPreMessageRequestMessages;
private final int jumpToPosition; private final int jumpToPosition;
ConversationData(long lastSeen, ConversationData(long lastSeen,
int lastSeenPosition,
boolean hasSent, boolean hasSent,
boolean isMessageRequestAccepted, boolean isMessageRequestAccepted,
boolean hasPreMessageRequestMessages, boolean hasPreMessageRequestMessages,
int jumpToPosition) int jumpToPosition)
{ {
this.lastSeen = lastSeen; this.lastSeen = lastSeen;
this.lastSeenPosition = lastSeenPosition;
this.hasSent = hasSent; this.hasSent = hasSent;
this.isMessageRequestAccepted = isMessageRequestAccepted; this.isMessageRequestAccepted = isMessageRequestAccepted;
this.hasPreMessageRequestMessages = hasPreMessageRequestMessages; this.hasPreMessageRequestMessages = hasPreMessageRequestMessages;
@ -24,8 +27,12 @@ final class ConversationData {
} }
long getLastSeen() { long getLastSeen() {
return lastSeen; return lastSeen;
} }
int getLastSeenPosition() {
return lastSeenPosition;
}
boolean hasSent() { boolean hasSent() {
return hasSent; return hasSent;

View file

@ -292,7 +292,7 @@ public class ConversationFragment extends Fragment {
} }
public void moveToLastSeen() { public void moveToLastSeen() {
if (conversationViewModel.getLastSeen() <= 0) { if (conversationViewModel.getLastSeenPosition() <= 0) {
Log.i(TAG, "No need to move to last seen."); Log.i(TAG, "No need to move to last seen.");
return; return;
} }
@ -302,7 +302,7 @@ public class ConversationFragment extends Fragment {
return; return;
} }
int position = getListAdapter().findLastSeenPosition(conversationViewModel.getLastSeen()); int position = getListAdapter().getAdapterPositionForMessagePosition(conversationViewModel.getLastSeenPosition());
scrollToLastSeenPosition(position); scrollToLastSeenPosition(position);
} }
@ -391,14 +391,13 @@ public class ConversationFragment extends Fragment {
private void initializeResources() { private void initializeResources() {
long oldThreadId = threadId; long oldThreadId = threadId;
long lastSeen = this.getActivity().getIntent().getLongExtra(ConversationActivity.LAST_SEEN_EXTRA, -1); int startingPosition = this.getActivity().getIntent().getIntExtra(ConversationActivity.STARTING_POSITION_EXTRA, -1);
int startingPosition = this.getActivity().getIntent().getIntExtra(ConversationActivity.STARTING_POSITION_EXTRA, -1);
this.recipient = Recipient.live(getActivity().getIntent().getParcelableExtra(ConversationActivity.RECIPIENT_EXTRA)); this.recipient = Recipient.live(getActivity().getIntent().getParcelableExtra(ConversationActivity.RECIPIENT_EXTRA));
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); this.unknownSenderView = new UnknownSenderView(getActivity(), recipient.get(), threadId);
conversationViewModel.onConversationDataAvailable(threadId, lastSeen, startingPosition); conversationViewModel.onConversationDataAvailable(threadId, startingPosition);
OnScrollListener scrollListener = new ConversationScrollListener(getActivity()); OnScrollListener scrollListener = new ConversationScrollListener(getActivity());
list.addOnScrollListener(scrollListener); list.addOnScrollListener(scrollListener);
@ -538,6 +537,7 @@ 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);
conversationViewModel.onConversationDataAvailable(threadId, -1);
initializeListAdapter(); initializeListAdapter();
} }
} }
@ -551,8 +551,6 @@ public class ConversationFragment extends Fragment {
} }
public void setLastSeen(long lastSeen) { public void setLastSeen(long lastSeen) {
conversationViewModel.onLastSeenChanged(lastSeen);
if (lastSeenDecoration != null) { if (lastSeenDecoration != null) {
list.removeItemDecoration(lastSeenDecoration); list.removeItemDecoration(lastSeenDecoration);
} }
@ -864,9 +862,7 @@ public class ConversationFragment extends Fragment {
adapter.setFooterView(null); adapter.setFooterView(null);
} }
if (conversationViewModel.getLastSeen() == -1) { setLastSeen(conversation.getLastSeen());
setLastSeen(conversation.getLastSeen());
}
if (FeatureFlags.messageRequests() && !conversation.hasPreMessageRequestMessages()) { if (FeatureFlags.messageRequests() && !conversation.hasPreMessageRequestMessages()) {
clearHeaderIfNotTyping(adapter); clearHeaderIfNotTyping(adapter);
@ -880,34 +876,25 @@ public class ConversationFragment extends Fragment {
listener.onCursorChanged(); listener.onCursorChanged();
list.post(() -> { int lastSeenPosition = adapter.getAdapterPositionForMessagePosition(conversation.getLastSeenPosition());
int lastSeenPosition = adapter.findLastSeenPosition(conversationViewModel.getLastSeen()); if (conversation.shouldJumpToMessage()) {
scrollToStartingPosition(conversation.getJumpToPosition());
if (isTypingIndicatorShowing()) { } else if (conversation.isMessageRequestAccepted()) {
lastSeenPosition = Math.max(lastSeenPosition - 1, 0); scrollToLastSeenPosition(lastSeenPosition);
} } else if (FeatureFlags.messageRequests()) {
list.post(() -> getListLayoutManager().scrollToPosition(adapter.getItemCount() - 1));
if (conversation.shouldJumpToMessage()) { }
scrollToStartingPosition(conversation.getJumpToPosition());
} else if (conversation.isMessageRequestAccepted()) {
scrollToLastSeenPosition(lastSeenPosition);
}
if (lastSeenPosition <= 0) {
setLastSeen(0);
}
});
} }
private void scrollToStartingPosition(final int startingPosition) { private void scrollToStartingPosition(int startingPosition) {
list.post(() -> { list.post(() -> {
list.getLayoutManager().scrollToPosition(startingPosition); list.getLayoutManager().scrollToPosition(startingPosition);
getListAdapter().pulseHighlightItem(startingPosition); getListAdapter().pulseHighlightItem(startingPosition);
}); });
} }
private void scrollToLastSeenPosition(final 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()));
} }

View file

@ -24,28 +24,34 @@ class ConversationRepository {
this.executor = SignalExecutors.BOUNDED; this.executor = SignalExecutors.BOUNDED;
} }
LiveData<ConversationData> getConversationData(long threadId, long lastSeen, int jumpToPosition) { LiveData<ConversationData> getConversationData(long threadId, int jumpToPosition) {
MutableLiveData<ConversationData> liveData = new MutableLiveData<>(); MutableLiveData<ConversationData> liveData = new MutableLiveData<>();
executor.execute(() -> { executor.execute(() -> {
liveData.postValue(getConversationDataInternal(threadId, lastSeen, jumpToPosition)); liveData.postValue(getConversationDataInternal(threadId, jumpToPosition));
}); });
return liveData; return liveData;
} }
private @NonNull ConversationData getConversationDataInternal(long threadId, long lastSeen, int jumpToPosition) { private @NonNull ConversationData getConversationDataInternal(long threadId, int jumpToPosition) {
Pair<Long, Boolean> lastSeenAndHasSent = DatabaseFactory.getThreadDatabase(context).getLastSeenAndHasSent(threadId); Pair<Long, Boolean> lastSeenAndHasSent = DatabaseFactory.getThreadDatabase(context).getLastSeenAndHasSent(threadId);
boolean hasSent = lastSeenAndHasSent.second(); long lastSeen = lastSeenAndHasSent.first();
boolean hasSent = lastSeenAndHasSent.second();
if (lastSeen == -1) { int lastSeenPosition = 0;
lastSeen = lastSeenAndHasSent.first();
}
boolean isMessageRequestAccepted = RecipientUtil.isMessageRequestAccepted(context, threadId); boolean isMessageRequestAccepted = RecipientUtil.isMessageRequestAccepted(context, threadId);
boolean hasPreMessageRequestMessages = RecipientUtil.isPreMessageRequestThread(context, threadId); boolean hasPreMessageRequestMessages = RecipientUtil.isPreMessageRequestThread(context, threadId);
return new ConversationData(lastSeen, hasSent, isMessageRequestAccepted, hasPreMessageRequestMessages, jumpToPosition); if (lastSeen > 0) {
lastSeenPosition = DatabaseFactory.getMmsSmsDatabase(context).getMessagePositionForLastSeen(threadId, lastSeen);
}
if (lastSeenPosition <= 0) {
lastSeen = 0;
}
return new ConversationData(lastSeen, lastSeenPosition, hasSent, isMessageRequestAccepted, hasPreMessageRequestMessages, jumpToPosition);
} }
} }

View file

@ -31,10 +31,9 @@ class ConversationViewModel extends ViewModel {
private final MutableLiveData<List<Media>> recentMedia; private final MutableLiveData<List<Media>> recentMedia;
private final MutableLiveData<Long> threadId; private final MutableLiveData<Long> threadId;
private final LiveData<PagedList<MessageRecord>> messages; private final LiveData<PagedList<MessageRecord>> messages;
private final LiveData<ConversationData> conversationMetadata; private final LiveData<ConversationData> conversationMetadata;
private int jumpToPosition; private int jumpToPosition;
private long lastSeen;
private ConversationViewModel() { private ConversationViewModel() {
this.context = ApplicationDependencies.getApplication(); this.context = ApplicationDependencies.getApplication();
@ -56,7 +55,7 @@ class ConversationViewModel extends ViewModel {
}); });
conversationMetadata = Transformations.switchMap(threadId, thread -> { conversationMetadata = Transformations.switchMap(threadId, thread -> {
LiveData<ConversationData> data = conversationRepository.getConversationData(thread, lastSeen, jumpToPosition); LiveData<ConversationData> data = conversationRepository.getConversationData(thread, jumpToPosition);
jumpToPosition = -1; jumpToPosition = -1;
return data; return data;
}); });
@ -66,17 +65,13 @@ class ConversationViewModel extends ViewModel {
mediaRepository.getMediaInBucket(context, Media.ALL_MEDIA_BUCKET_ID, recentMedia::postValue); mediaRepository.getMediaInBucket(context, Media.ALL_MEDIA_BUCKET_ID, recentMedia::postValue);
} }
void onConversationDataAvailable(long threadId, long lastSeen, int startingPosition) { void onConversationDataAvailable(long threadId, int startingPosition) {
this.lastSeen = lastSeen; Log.d(TAG, "[onConversationDataAvailable] threadId: " + threadId + ", startingPosition: " + startingPosition);
this.jumpToPosition = startingPosition; this.jumpToPosition = startingPosition;
this.threadId.setValue(threadId); this.threadId.setValue(threadId);
} }
void onLastSeenChanged(long lastSeen) {
this.lastSeen = lastSeen;
}
@NonNull LiveData<List<Media>> getRecentMedia() { @NonNull LiveData<List<Media>> getRecentMedia() {
return recentMedia; return recentMedia;
} }
@ -90,7 +85,11 @@ class ConversationViewModel extends ViewModel {
} }
long getLastSeen() { long getLastSeen() {
return lastSeen; return conversationMetadata.getValue() != null ? conversationMetadata.getValue().getLastSeen() : 0;
}
int getLastSeenPosition() {
return conversationMetadata.getValue() != null ? conversationMetadata.getValue().getLastSeenPosition() : 0;
} }
static class Factory extends ViewModelProvider.NewInstanceFactory { static class Factory extends ViewModelProvider.NewInstanceFactory {

View file

@ -347,7 +347,6 @@ 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.getLastSeen(),
-1); -1);
} }
@ -360,7 +359,6 @@ public class ConversationListFragment extends MainFragment implements LoaderMana
getNavigator().goToConversation(contact.getId(), getNavigator().goToConversation(contact.getId(),
threadId, threadId,
ThreadDatabase.DistributionTypes.DEFAULT, ThreadDatabase.DistributionTypes.DEFAULT,
-1,
-1); -1);
}); });
} }
@ -375,7 +373,6 @@ 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,
-1,
startingPosition); startingPosition);
}); });
} }
@ -691,8 +688,8 @@ public class ConversationListFragment extends MainFragment implements LoaderMana
actionMode.setTitle(String.valueOf(defaultAdapter.getBatchSelections().size())); actionMode.setTitle(String.valueOf(defaultAdapter.getBatchSelections().size()));
} }
private void handleCreateConversation(long threadId, Recipient recipient, int distributionType, long lastSeen) { private void handleCreateConversation(long threadId, Recipient recipient, int distributionType) {
getNavigator().goToConversation(recipient.getId(), threadId, distributionType, lastSeen, -1); getNavigator().goToConversation(recipient.getId(), threadId, distributionType, -1);
} }
@Override @Override
@ -726,8 +723,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(), handleCreateConversation(item.getThreadId(), item.getRecipient(), item.getDistributionType());
item.getDistributionType(), item.getLastSeen());
} else { } else {
ConversationListAdapter adapter = (ConversationListAdapter)list.getAdapter(); ConversationListAdapter adapter = (ConversationListAdapter)list.getAdapter();
adapter.toggleThreadInBatchSet(item.getThreadId()); adapter.toggleThreadInBatchSet(item.getThreadId());

View file

@ -125,6 +125,18 @@ public class MmsSmsDatabase extends Database {
return new Pair<>(id, latestQuit); return new Pair<>(id, latestQuit);
} }
public int getMessagePositionForLastSeen(long threadId, long lastSeen) {
String[] projection = new String[] { "COUNT(*)" };
String selection = MmsSmsColumns.THREAD_ID + " = " + threadId + " AND " + MmsSmsColumns.NORMALIZED_DATE_RECEIVED + " > " + lastSeen;
try (Cursor cursor = queryTables(projection, selection, null, null)) {
if (cursor != null && cursor.moveToNext()) {
return cursor.getInt(0);
}
}
return 0;
}
public @Nullable MessageRecord getMessageFor(long timestamp, RecipientId author) { public @Nullable MessageRecord getMessageFor(long timestamp, RecipientId author) {
MmsSmsDatabase db = DatabaseFactory.getMmsSmsDatabase(context); MmsSmsDatabase db = DatabaseFactory.getMmsSmsDatabase(context);

View file

@ -80,7 +80,7 @@ public class NotificationItem {
public PendingIntent getPendingIntent(Context context) { public PendingIntent getPendingIntent(Context context) {
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;
Intent intent = ConversationActivity.buildIntent(context, recipient.getId(), threadId, 0, -1, startingPosition); Intent intent = ConversationActivity.buildIntent(context, recipient.getId(), threadId, 0, startingPosition);
makeIntentUniqueToPreventMerging(intent); makeIntentUniqueToPreventMerging(intent);