unread: Fix process_visible race with fetching.

The previous batch of improvements to this code path in
6562ea94e4 introduced a race bug where:

- You navigate to a narrowed view; Zulip renders cached data from
  `all_messages_data` that we know is current, but
  `fetch_status.has_found_newest` is initialized to `false`
  nonetheless.

- The bottom is visible, triggering the check for whether the view
  should be marked as read.

- `fetch_status.has_found_newest` is still `false`, and so we
  incorrectly refuse to mark as read.

- We finish fetching data from the server, do the background rerender
  for that (with no changes), but that doesn't trigger a re-check for
  whether the bottom is visible.

There's several ways to address this, but most correct to me is to not
check fetch_status in this particular code path.

The same reasoning applies to the navigate.js call sites.
This commit is contained in:
Tim Abbott
2024-02-05 18:36:41 -08:00
parent b8562bf7b4
commit b9af5ce86e
4 changed files with 24 additions and 16 deletions

View File

@@ -1439,16 +1439,21 @@ export class MessageListView {
this.message_containers.clear();
}
is_fetched_end_rendered() {
return this._render_win_end === this.list.num_items();
}
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()
);
return this.is_fetched_end_rendered() && this.list.data.fetch_status.has_found_newest();
}
is_fetched_start_rendered() {
return this._render_win_start === 0;
}
is_start_rendered() {
@@ -1457,7 +1462,7 @@ export class MessageListView {
// fail to be for two reasons: Either some older messages are
// not rendered due to a render window, or we haven't finished
// fetching the oldest messages for this view from the server.
return this._render_win_start === 0 && this.list.data.fetch_status.has_found_oldest();
return this.is_fetched_start_rendered() && this.list.data.fetch_status.has_found_oldest();
}
get_row(id) {