Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,10 @@ public boolean canRestorePinnedMessage () {
}

public void destroy (ViewController<?> context) {
if (isFocused) {
flushReadAndScrollState();
isFocused = false;
}
resetScroll();
returnToMessageIds = null;
highlightMode = 0;
Expand Down Expand Up @@ -2516,11 +2520,16 @@ private void setFocused (boolean isFocused) {
if (Log.isEnabled(Log.TAG_MESSAGES_LOADER)) {
Log.i(Log.TAG_MESSAGES_LOADER, "MessagesManager isFocused -> %b", isFocused);
}
this.isFocused = isFocused;
if (isFocused) {
this.isFocused = true;
onFocus();
} else {
// Flush while the viewport still accepts view requests. Both
// allowViewRequest() and saveScrollPosition() reject an unfocused
// controller, so changing the flag first discarded the final topic
// read boundary and scroll anchor.
onBlur();
this.isFocused = false;
}
}
}
Expand Down Expand Up @@ -2560,6 +2569,19 @@ public boolean isFocused () {
}

private void onBlur () {
flushReadAndScrollState();
}

private void flushReadAndScrollState () {
// The viewport batches ViewMessages calls. Force one final pass before it
// is recycled, then explicitly submit every message still visible. The
// second call is intentional: a message may no longer be marked "recent"
// after an earlier asynchronous request, but TDLib still needs the final
// forum-topic read boundary when the chat is closed immediately after it.
viewMessages(false);
if (messageViewer != null && canRead()) {
loader.viewport().viewMessages(false, true, null);
Comment on lines +2582 to +2583

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Respect focus before forcing topic reads

When prepareForTopicSwitch() is invoked while the controller is unfocused, this direct call bypasses the viewport callback's allowViewRequest() check and marks every tracked message as read because canRead() does not test focus. This can occur, for example, when the asynchronous DeleteForumTopic response in MessagesController calls setForumTopic(null) after the user has already navigated away, potentially marking messages loaded while the screen was in the background as read. Guard the forced submission with the manager's focused state while retaining it for the blur/destroy paths, which deliberately flush before clearing that state.

Useful? React with 👍 / 👎.

}
saveScrollPosition();
}

Expand Down Expand Up @@ -2682,11 +2704,7 @@ private void saveScrollPosition () {
}

public void prepareForTopicSwitch () {
// Flush both TDLib's read state and the topic-specific scroll anchor before
// the loader is rebound to another topic. Otherwise the next opening can
// reuse the position that was saved when the topic was first opened.
viewMessages(false);
saveScrollPosition();
flushReadAndScrollState();
}

public void onMissedMessagesHintReceived () {
Expand Down
Loading