message_view: Attempt rendering cached data without contacting server.

For narrows for which we cannot filter the messages locally,
we attempt to select a message without contacting the server.
This commit is contained in:
Aman Agrawal 2024-11-02 19:19:03 +05:30 committed by Tim Abbott
parent 4b6fd4057c
commit 88d0328e49
2 changed files with 48 additions and 0 deletions

View File

@ -978,6 +978,34 @@ export function maybe_add_local_messages(opts: {
// below), but the server doesn't support that query.
id_info.final_select_id = id_info.target_id;
}
// If we have cached data for the same narrow, we can try to find the
// message we want to select locally.
if (superset_data.filter.equals(filter) && !load_local_messages(msg_data, superset_data)) {
return;
}
// Even for the `cannot_compute` case, we can render locally
// under specific conditions.
if (
// If we locally have the message user wants to select.
id_info.target_id &&
msg_data.get(id_info.target_id) &&
// We don't want to accidentally mark old unreads as read,
// so we only render if cannot mark messages read in this view
// which is commonly the case in this code path.
!filter.can_mark_messages_read()
) {
id_info.local_select_id = id_info.target_id;
} else if (
id_info.target_id === undefined &&
// Our goal here is to select the first unread id. We can only do
// so if we have the complete data for the narrow.
msg_data.fetch_status.has_found_newest() &&
msg_data.fetch_status.has_found_oldest()
) {
id_info.local_select_id = msg_data.first_unread_message_id();
}
// if we can't compute a next unread id, just return without
// setting local_select_id, so that we go to the server.
return;

View File

@ -47,6 +47,7 @@ function test_with(fixture) {
all_messages_data.rewire_all_messages_data({
fetch_status: {
has_found_newest: () => fixture.has_found_newest,
has_found_oldest: () => fixture.has_found_newest,
},
visibly_empty: () => fixture.visibly_empty,
all_messages() {
@ -61,6 +62,9 @@ function test_with(fixture) {
assert.notEqual(fixture.all_messages, undefined);
return fixture.all_messages.at(-1);
},
filter: {
equals: () => false,
},
});
narrow_state.rewire_get_first_unread_info(() => fixture.unread_info);
@ -89,6 +93,7 @@ run_test("near after unreads", () => {
msg_id: 37,
},
has_found_newest: false,
has_found_oldest: false,
all_messages: [
{id: 37, topic: "whatever"},
{id: 42, topic: "whatever"},
@ -116,6 +121,7 @@ run_test("near not in message list", () => {
msg_id: 46,
},
has_found_newest: false,
has_found_oldest: false,
all_messages: [
{id: 41, topic: "whatever"},
{id: 45, topic: "whatever"},
@ -141,6 +147,7 @@ run_test("near before unreads", () => {
msg_id: 43,
},
has_found_newest: false,
has_found_oldest: false,
all_messages: [
{id: 42, topic: "whatever"},
{id: 43, topic: "whatever"},
@ -165,6 +172,7 @@ run_test("near with no unreads", () => {
flavor: "not_found",
},
has_found_newest: false,
has_found_oldest: false,
visibly_empty: true,
expected_id_info: {
target_id: 42,
@ -185,6 +193,7 @@ run_test("is private with no target", () => {
msg_id: 550,
},
has_found_newest: true,
has_found_oldest: false,
all_messages: [
{id: 450, type: "private", to_user_ids: "1,2"},
{id: 500, type: "private", to_user_ids: "1,2"},
@ -209,6 +218,7 @@ run_test("dm with target outside of range", () => {
flavor: "not_found",
},
has_found_newest: false,
has_found_oldest: false,
all_messages: [{id: 999}],
expected_id_info: {
target_id: 5,
@ -228,6 +238,7 @@ run_test("is:private with no unreads before fetch", () => {
flavor: "not_found",
},
has_found_newest: false,
has_found_oldest: false,
visibly_empty: true,
expected_id_info: {
target_id: undefined,
@ -248,6 +259,7 @@ run_test("is:private with target and no unreads", () => {
flavor: "not_found",
},
has_found_newest: true,
has_found_oldest: false,
visibly_empty: false,
all_messages: [
{id: 350},
@ -273,6 +285,7 @@ run_test("is:mentioned with no unreads and no matches", () => {
flavor: "not_found",
},
has_found_newest: true,
has_found_oldest: false,
all_messages: [],
expected_id_info: {
target_id: undefined,
@ -292,6 +305,7 @@ run_test("is:alerted with no unreads and one match", () => {
flavor: "not_found",
},
has_found_newest: true,
has_found_oldest: false,
all_messages: [
{id: 55, topic: "whatever", alerted: true},
{id: 57, topic: "whatever", alerted: false},
@ -316,6 +330,7 @@ run_test("is:resolved with one unread", () => {
msg_id: 56,
},
has_found_newest: true,
has_found_oldest: false,
all_messages: [
{id: 55, type: "stream", topic: resolved_topic_name},
{id: 56, type: "stream", topic: resolved_topic_name},
@ -340,6 +355,7 @@ run_test("is:resolved with no unreads", () => {
flavor: "not_found",
},
has_found_newest: true,
has_found_oldest: false,
all_messages: [
{id: 55, type: "stream", topic: resolved_topic_name},
{id: 57, type: "stream", topic: "foo"},
@ -407,6 +423,7 @@ run_test("stream, no unread, not in all_messages", () => {
flavor: "not_found",
},
has_found_newest: true,
has_found_oldest: false,
visibly_empty: false,
all_messages: [{id: 400}, {id: 500}],
expected_id_info: {
@ -430,6 +447,7 @@ run_test("search, stream, not in all_messages", () => {
flavor: "cannot_compute",
},
has_found_newest: true,
has_found_oldest: false,
visibly_empty: false,
all_messages: [{id: 400}, {id: 500}],
expected_id_info: {
@ -459,6 +477,7 @@ run_test("stream/topic not in all_messages", () => {
msg_id: 2,
},
has_found_newest: true,
has_found_oldest: false,
all_messages: [{id: 900}, {id: 1100}],
expected_id_info: {
target_id: 1000,
@ -482,6 +501,7 @@ run_test("final corner case", () => {
flavor: "not_found",
},
has_found_newest: true,
has_found_oldest: false,
visibly_empty: false,
all_messages: [
{id: 400, topic: "whatever"},