unread: Stop treating bottom of render windows as the global bottom.

The previous logic for both scrolling down and using pagedown would
incorrectly mark an entire conversation as read when reaching the
bottom of a render window, even if there were more messages loaded or
to fetch from the server.

Fix this error in the calculation by asking the correct data
structures if we're actually at the bottom.

To avoid the navigate.js keyboard shortcut code paths circumventing
this new logic, or needing to duplicate it, they now call
process_visible, rather than its helper.
This commit is contained in:
Tim Abbott 2024-01-31 13:22:34 -08:00
parent da7cb0af1c
commit 6562ea94e4
4 changed files with 26 additions and 6 deletions

View File

@ -1439,6 +1439,18 @@ export class MessageListView {
this.message_containers.clear();
}
is_end_rendered() {
// Used as a helper in checks for whether a given scroll
// position is actually the very end of this view. It could
// fail to be for two reasons: Either some newer messages are
// not rendered due to a render window, or we haven't finished
// fetching the newest messages for this view from the server.
return (
this._render_win_end === this.list.num_items() &&
this.list.data.fetch_status.has_found_newest()
);
}
get_row(id) {
const $row = this._rows.get(id);

View File

@ -71,6 +71,10 @@ export function message_viewport_info(): MessageViewportInfo {
};
}
// Important note: These functions just look at the state of the
// rendered message feed; messages that are not displayed due to a
// limited render window or because they have not been fetched from
// the server are not considered.
export function at_bottom(): boolean {
const bottom = scrollTop() + height();
const full_height = $scroll_container.prop("scrollHeight");

View File

@ -26,7 +26,7 @@ export function down(with_centering) {
message_viewport.scrollTop(
($current_msg_list.outerHeight(true) ?? 0) - message_viewport.height() * 0.1,
);
unread_ops.process_scrolled_to_bottom();
unread_ops.process_visible();
}
return;
@ -50,7 +50,7 @@ export function to_end() {
const next_id = message_lists.current.last().id;
message_viewport.set_last_movement_direction(1);
message_lists.current.select_id(next_id, {then_scroll: true, from_scroll: true});
unread_ops.process_scrolled_to_bottom();
unread_ops.process_visible();
}
function amount_to_paginate() {
@ -110,7 +110,7 @@ export function page_up() {
export function page_down() {
if (message_viewport.at_bottom() && !message_lists.current.visibly_empty()) {
message_lists.current.select_id(message_lists.current.last().id, {then_scroll: false});
unread_ops.process_scrolled_to_bottom();
unread_ops.process_visible();
} else {
page_down_the_right_amount();
}

View File

@ -435,7 +435,7 @@ export function notify_server_message_read(message, options) {
notify_server_messages_read([message], options);
}
export function process_scrolled_to_bottom() {
function process_scrolled_to_bottom() {
if (!narrow_state.is_message_feed_visible()) {
// First, verify the current message list is visible.
return;
@ -455,9 +455,13 @@ export function process_scrolled_to_bottom() {
}
// If we ever materially change the algorithm for this function, we
// may need to update notifications.received_messages as well.
// may need to update message_notifications.received_messages as well.
export function process_visible() {
if (viewport_is_visible_and_focused() && message_viewport.bottom_message_visible()) {
if (
viewport_is_visible_and_focused() &&
message_viewport.bottom_message_visible() &&
message_lists.current.view.is_end_rendered()
) {
process_scrolled_to_bottom();
}
}