message_events: Discard message list that cannot be live updated.

Since we cannot cheaply live update `is-followed` narrow, we
discard any message list or data with that narrow if we
received a message event that changes topic visibility
from or to `FOLLOWED`.
This commit is contained in:
Aman Agrawal 2024-10-27 12:52:53 +05:30 committed by Tim Abbott
parent 517fabd123
commit e6113b0dd4
5 changed files with 65 additions and 2 deletions

View File

@ -47,6 +47,34 @@ function filter_has_term_type(filter, term_type) {
);
}
export function discard_cached_lists_with_term_type(term_type) {
// Discards cached MessageList and MessageListData which have
// `term_type` and `not-term_type`.
assert(!term_type.includes("not-"));
// We loop over rendered message lists and cached message data separately since
// they are separately maintained and can have different items.
for (const msg_list of message_lists.all_rendered_message_lists()) {
// We never want to discard the current message list.
if (msg_list === message_lists.current) {
continue;
}
const filter = msg_list.data.filter;
if (filter_has_term_type(filter, term_type)) {
message_lists.delete_message_list(msg_list);
message_list_data_cache.remove(filter);
}
}
for (const msg_list_data of message_lists.non_rendered_data()) {
const filter = msg_list_data.filter;
if (filter_has_term_type(filter, term_type)) {
message_list_data_cache.remove(filter);
}
}
}
export function update_current_view_for_topic_visibility() {
// If we have rendered message list / cached data based on topic
// visibility policy, we need to rerender it to reflect the changes. It

View File

@ -15,7 +15,7 @@ export function set_current(msg_list: MessageList | undefined): void {
current = msg_list;
}
function delete_message_list(message_list: MessageList): void {
export function delete_message_list(message_list: MessageList): void {
message_list.view.$list.remove();
rendered_message_lists.delete(message_list.id);
message_list.data.set_rendered_message_list_id(undefined);

View File

@ -90,6 +90,7 @@ import * as user_group_edit from "./user_group_edit";
import * as user_groups from "./user_groups";
import {user_settings} from "./user_settings";
import * as user_status from "./user_status";
import * as user_topics from "./user_topics";
import * as user_topics_ui from "./user_topics_ui";
export function dispatch_normal_event(event) {
@ -1017,11 +1018,23 @@ export function dispatch_normal_event(event) {
}
break;
case "user_topic":
case "user_topic": {
const previous_topic_visibility = user_topics.get_topic_visibility_policy(
event.stream_id,
event.topic_name,
);
user_topics_ui.handle_topic_updates(
event,
message_events.update_current_view_for_topic_visibility(),
);
// Discard cached message lists if `event` topic was / is followed.
if (
event.visibility_policy === user_topics.all_visibility_policies.FOLLOWED ||
previous_topic_visibility === user_topics.all_visibility_policies.FOLLOWED
) {
message_events.discard_cached_lists_with_term_type("is-followed");
}
break;
}
}
}

View File

@ -379,6 +379,20 @@ run_test("muted_topics", ({override}) => {
assert_same(args.user_topic, event);
});
run_test("followed_topic", ({override}) => {
const event = event_fixtures.user_topic_with_followed_policy_change;
const stub = make_stub();
const discard_msg_list_stub = make_stub();
override(user_topics_ui, "handle_topic_updates", stub.f);
override(message_events, "discard_cached_lists_with_term_type", discard_msg_list_stub.f);
dispatch(event);
assert.equal(stub.num_calls, 1);
assert.equal(discard_msg_list_stub.num_calls, 1);
const args = stub.get_args("user_topic");
assert_same(args.user_topic, event);
});
run_test("muted_users", ({override}) => {
const event = event_fixtures.muted_users;

View File

@ -1164,6 +1164,14 @@ exports.fixtures = {
visibility_policy: 1,
},
user_topic_with_followed_policy_change: {
type: "user_topic",
stream_id: 101,
topic_name: "js",
last_updated: fake_now,
visibility_policy: 3,
},
web_reload_client: {
type: "web_reload_client",
immediate: true,