mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-26 03:40:56 +01:00
Return to previous scroll position when returning to a conversation.
This commit is contained in:
committed by
Greyson Parrelli
parent
a9ea1d7606
commit
5b2a399392
@@ -510,6 +510,10 @@ public class ConversationAdapter<V extends View & BindableConversationItem>
|
||||
}
|
||||
}
|
||||
|
||||
public @Nullable MessageRecord getLastVisibleMessageRecord(int position) {
|
||||
return getItem(position - ((hasFooter() && position == getItemCount() - 1) ? 1 : 0));
|
||||
}
|
||||
|
||||
static class ConversationViewHolder extends RecyclerView.ViewHolder {
|
||||
public <V extends View & BindableConversationItem> ConversationViewHolder(final @NonNull V itemView) {
|
||||
super(itemView);
|
||||
|
||||
@@ -7,6 +7,7 @@ final class ConversationData {
|
||||
private final long threadId;
|
||||
private final long lastSeen;
|
||||
private final int lastSeenPosition;
|
||||
private final int lastScrolledPosition;
|
||||
private final boolean hasSent;
|
||||
private final boolean isMessageRequestAccepted;
|
||||
private final boolean hasPreMessageRequestMessages;
|
||||
@@ -15,18 +16,20 @@ final class ConversationData {
|
||||
ConversationData(long threadId,
|
||||
long lastSeen,
|
||||
int lastSeenPosition,
|
||||
int lastScrolledPosition,
|
||||
boolean hasSent,
|
||||
boolean isMessageRequestAccepted,
|
||||
boolean hasPreMessageRequestMessages,
|
||||
int jumpToPosition)
|
||||
{
|
||||
this.threadId = threadId;
|
||||
this.lastSeen = lastSeen;
|
||||
this.lastSeenPosition = lastSeenPosition;
|
||||
this.hasSent = hasSent;
|
||||
this.isMessageRequestAccepted = isMessageRequestAccepted;
|
||||
this.hasPreMessageRequestMessages = hasPreMessageRequestMessages;
|
||||
this.jumpToPosition = jumpToPosition;
|
||||
this.threadId = threadId;
|
||||
this.lastSeen = lastSeen;
|
||||
this.lastSeenPosition = lastSeenPosition;
|
||||
this.lastScrolledPosition = lastScrolledPosition;
|
||||
this.hasSent = hasSent;
|
||||
this.isMessageRequestAccepted = isMessageRequestAccepted;
|
||||
this.hasPreMessageRequestMessages = hasPreMessageRequestMessages;
|
||||
this.jumpToPosition = jumpToPosition;
|
||||
}
|
||||
|
||||
public long getThreadId() {
|
||||
@@ -41,6 +44,10 @@ final class ConversationData {
|
||||
return lastSeenPosition;
|
||||
}
|
||||
|
||||
int getLastScrolledPosition() {
|
||||
return lastScrolledPosition;
|
||||
}
|
||||
|
||||
boolean hasSent() {
|
||||
return hasSent;
|
||||
}
|
||||
@@ -57,6 +64,10 @@ final class ConversationData {
|
||||
return jumpToPosition >= 0;
|
||||
}
|
||||
|
||||
boolean shouldScrollToLastSeen() {
|
||||
return lastSeenPosition > 0;
|
||||
}
|
||||
|
||||
int getJumpToPosition() {
|
||||
return jumpToPosition;
|
||||
}
|
||||
|
||||
@@ -284,6 +284,23 @@ public class ConversationFragment extends Fragment {
|
||||
initializeTypingObserver();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
int lastVisiblePosition = getListLayoutManager().findLastVisibleItemPosition();
|
||||
int firstVisiblePosition = getListLayoutManager().findFirstCompletelyVisibleItemPosition();
|
||||
|
||||
final long lastVisibleMessageTimestamp;
|
||||
if (firstVisiblePosition != 0 && lastVisiblePosition != RecyclerView.NO_POSITION) {
|
||||
MessageRecord message = getListAdapter().getLastVisibleMessageRecord(lastVisiblePosition);
|
||||
|
||||
lastVisibleMessageTimestamp = message != null ? message.getDateReceived() : 0;
|
||||
} else {
|
||||
lastVisibleMessageTimestamp = 0;
|
||||
}
|
||||
SignalExecutors.BOUNDED.submit(() -> DatabaseFactory.getThreadDatabase(requireContext()).setLastScrolled(threadId, lastVisibleMessageTimestamp));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
@@ -312,7 +329,7 @@ public class ConversationFragment extends Fragment {
|
||||
}
|
||||
|
||||
int position = getListAdapter().getAdapterPositionForMessagePosition(conversationViewModel.getLastSeenPosition());
|
||||
scrollToLastSeenPosition(position);
|
||||
scrollToPosition(position);
|
||||
}
|
||||
|
||||
private void initializeMessageRequestViewModel() {
|
||||
@@ -886,12 +903,13 @@ public class ConversationFragment extends Fragment {
|
||||
|
||||
listener.onCursorChanged();
|
||||
|
||||
int lastSeenPosition = adapter.getAdapterPositionForMessagePosition(conversation.getLastSeenPosition());
|
||||
int lastSeenPosition = adapter.getAdapterPositionForMessagePosition(conversation.getLastSeenPosition());
|
||||
int lastScrolledPosition = adapter.getAdapterPositionForMessagePosition(conversation.getLastScrolledPosition());
|
||||
|
||||
if (conversation.shouldJumpToMessage()) {
|
||||
scrollToStartingPosition(conversation.getJumpToPosition());
|
||||
} else if (conversation.isMessageRequestAccepted()) {
|
||||
scrollToLastSeenPosition(lastSeenPosition);
|
||||
scrollToPosition(conversation.shouldScrollToLastSeen() ? lastSeenPosition : lastScrolledPosition);
|
||||
} else if (FeatureFlags.messageRequests()) {
|
||||
list.post(() -> getListLayoutManager().scrollToPosition(adapter.getItemCount() - 1));
|
||||
}
|
||||
@@ -904,9 +922,9 @@ public class ConversationFragment extends Fragment {
|
||||
});
|
||||
}
|
||||
|
||||
private void scrollToLastSeenPosition(int lastSeenPosition) {
|
||||
if (lastSeenPosition > 0) {
|
||||
list.post(() -> getListLayoutManager().scrollToPositionWithOffset(lastSeenPosition, list.getHeight()));
|
||||
private void scrollToPosition(int position) {
|
||||
if (position > 0) {
|
||||
list.post(() -> getListLayoutManager().scrollToPositionWithOffset(position, list.getHeight()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,10 +7,10 @@ import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientUtil;
|
||||
import org.thoughtcrime.securesms.util.concurrent.SignalExecutors;
|
||||
import org.whispersystems.libsignal.util.Pair;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
@@ -35,23 +35,29 @@ class ConversationRepository {
|
||||
}
|
||||
|
||||
private @NonNull ConversationData getConversationDataInternal(long threadId, int jumpToPosition) {
|
||||
Pair<Long, Boolean> lastSeenAndHasSent = DatabaseFactory.getThreadDatabase(context).getLastSeenAndHasSent(threadId);
|
||||
ThreadDatabase.ConversationMetadata metadata = DatabaseFactory.getThreadDatabase(context).getConversationMetadata(threadId);
|
||||
|
||||
long lastSeen = lastSeenAndHasSent.first();
|
||||
boolean hasSent = lastSeenAndHasSent.second();
|
||||
int lastSeenPosition = 0;
|
||||
long lastSeen = metadata.getLastSeen();
|
||||
boolean hasSent = metadata.hasSent();
|
||||
int lastSeenPosition = 0;
|
||||
long lastScrolled = metadata.getLastScrolled();
|
||||
int lastScrolledPosition = 0;
|
||||
|
||||
boolean isMessageRequestAccepted = RecipientUtil.isMessageRequestAccepted(context, threadId);
|
||||
boolean hasPreMessageRequestMessages = RecipientUtil.isPreMessageRequestThread(context, threadId);
|
||||
|
||||
if (lastSeen > 0) {
|
||||
lastSeenPosition = DatabaseFactory.getMmsSmsDatabase(context).getMessagePositionForLastSeen(threadId, lastSeen);
|
||||
lastSeenPosition = DatabaseFactory.getMmsSmsDatabase(context).getMessagePositionOnOrAfterTimestamp(threadId, lastSeen);
|
||||
}
|
||||
|
||||
if (lastSeenPosition <= 0) {
|
||||
lastSeen = 0;
|
||||
}
|
||||
|
||||
return new ConversationData(threadId, lastSeen, lastSeenPosition, hasSent, isMessageRequestAccepted, hasPreMessageRequestMessages, jumpToPosition);
|
||||
if (lastSeen == 0 && lastScrolled > 0) {
|
||||
lastScrolledPosition = DatabaseFactory.getMmsSmsDatabase(context).getMessagePositionOnOrAfterTimestamp(threadId, lastScrolled);
|
||||
}
|
||||
|
||||
return new ConversationData(threadId, lastSeen, lastSeenPosition, lastScrolledPosition, hasSent, isMessageRequestAccepted, hasPreMessageRequestMessages, jumpToPosition);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,11 +70,13 @@ class ConversationViewModel extends ViewModel {
|
||||
final int startPosition;
|
||||
if (data.shouldJumpToMessage()) {
|
||||
startPosition = data.getJumpToPosition();
|
||||
} else {
|
||||
} else if (data.shouldScrollToLastSeen()) {
|
||||
startPosition = data.getLastSeenPosition();
|
||||
} else {
|
||||
startPosition = data.getLastScrolledPosition();
|
||||
}
|
||||
|
||||
Log.d(TAG, "Starting at position " + startPosition + " :: " + data.getJumpToPosition() + " :: " + data.getLastSeenPosition());
|
||||
Log.d(TAG, "Starting at position startPosition: " + startPosition + " jumpToPosition: " + jumpToPosition + " lastSeenPosition: " + data.getLastSeenPosition() + " lastScrolledPosition: " + data.getLastScrolledPosition());
|
||||
|
||||
return Transformations.map(new LivePagedListBuilder<>(factory, config).setFetchExecutor(ConversationDataSource.EXECUTOR)
|
||||
.setInitialLoadKey(Math.max(startPosition, 0))
|
||||
|
||||
Reference in New Issue
Block a user