diff --git a/web/src/user_topics.js b/web/src/user_topics.js index 53b938facd..a950e88f79 100644 --- a/web/src/user_topics.js +++ b/web/src/user_topics.js @@ -10,7 +10,7 @@ import * as stream_data from "./stream_data"; import * as timerender from "./timerender"; import {get_time_from_date_muted} from "./util"; -const muted_topics = new Map(); +const all_user_topics = new Map(); export const all_visibility_policies = { INHERIT: 0, @@ -19,45 +19,56 @@ export const all_visibility_policies = { FOLLOWED: 3, }; -export function add_muted_topic(stream_id, topic, date_muted) { - let sub_dict = muted_topics.get(stream_id); - if (!sub_dict) { - sub_dict = new FoldDict(); - muted_topics.set(stream_id, sub_dict); - } - const time = get_time_from_date_muted(date_muted); - sub_dict.set(topic, time); -} - -export function remove_muted_topic(stream_id, topic) { - const sub_dict = muted_topics.get(stream_id); - if (sub_dict) { +export function update_user_topics(stream_id, topic, visibility_policy, date_updated) { + let sub_dict = all_user_topics.get(stream_id); + if (visibility_policy === all_visibility_policies.INHERIT && sub_dict) { sub_dict.delete(topic); + } else { + if (!sub_dict) { + sub_dict = new FoldDict(); + all_user_topics.set(stream_id, sub_dict); + } + const time = get_time_from_date_muted(date_updated); + sub_dict.set(topic, {date_updated: time, visibility_policy}); } } -export function is_topic_muted(stream_id, topic) { +export function get_topic_visibility_policy(stream_id, topic) { if (stream_id === undefined) { return false; } - const sub_dict = muted_topics.get(stream_id); - return (sub_dict && sub_dict.get(topic)) || false; + const sub_dict = all_user_topics.get(stream_id); + if (sub_dict && sub_dict.get(topic)) { + return sub_dict.get(topic).visibility_policy; + } + + return all_visibility_policies.INHERIT; +} + +export function is_topic_unmuted(stream_id, topic) { + return get_topic_visibility_policy(stream_id, topic) === all_visibility_policies.UNMUTED; +} + +export function is_topic_muted(stream_id, topic) { + return get_topic_visibility_policy(stream_id, topic) === all_visibility_policies.MUTED; } export function get_muted_topics() { const topics = []; - for (const [stream_id, sub_dict] of muted_topics) { + for (const [stream_id, sub_dict] of all_user_topics) { const stream = stream_data.maybe_get_stream_name(stream_id); for (const topic of sub_dict.keys()) { - const date_muted = sub_dict.get(topic); - const date_muted_str = timerender.render_now(new Date(date_muted)).time_str; - topics.push({ - stream_id, - stream, - topic, - date_muted, - date_muted_str, - }); + if (sub_dict.get(topic).visibility_policy === all_visibility_policies.MUTED) { + const date_muted = sub_dict.get(topic).date_updated; + const date_muted_str = timerender.render_now(new Date(date_muted)).time_str; + topics.push({ + stream_id, + stream, + topic, + date_muted, + date_muted_str, + }); + } } } return topics; @@ -114,7 +125,7 @@ export function set_user_topic_visibility_policy(stream_id, topic, visibility_po export function set_user_topic(user_topic) { const stream_id = user_topic.stream_id; const topic = user_topic.topic_name; - const date_muted = user_topic.last_updated; + const date_updated = user_topic.last_updated; const stream_name = stream_data.maybe_get_stream_name(stream_id); @@ -123,18 +134,11 @@ export function set_user_topic(user_topic) { return; } - switch (user_topic.visibility_policy) { - case visibility_policy.MUTED: - add_muted_topic(stream_id, topic, date_muted); - break; - case visibility_policy.INHERIT: - remove_muted_topic(stream_id, topic); - break; - } + update_user_topics(stream_id, topic, user_topic.visibility_policy, date_updated); } export function set_user_topics(user_topics) { - muted_topics.clear(); + all_user_topics.clear(); for (const user_topic of user_topics) { set_user_topic(user_topic); diff --git a/web/tests/message_list_data.test.js b/web/tests/message_list_data.test.js index 6cda52f8ab..9c83a4d4bd 100644 --- a/web/tests/message_list_data.test.js +++ b/web/tests/message_list_data.test.js @@ -143,7 +143,7 @@ run_test("muting", () => { {id: 9, type: "private", to_user_ids: "9", sender_id: 11}, // 1:1 PM to non-muted ]; - user_topics.add_muted_topic(1, "muted"); + user_topics.update_user_topics(1, "muted", user_topics.all_visibility_policies.MUTED); muted_users.add_muted_user(10); // `messages_filtered_for_topic_mutes` should skip filtering diff --git a/web/tests/notifications.test.js b/web/tests/notifications.test.js index 40b72f8cd0..6ef99f45da 100644 --- a/web/tests/notifications.test.js +++ b/web/tests/notifications.test.js @@ -47,7 +47,11 @@ const muted = { stream_data.add_sub(general); stream_data.add_sub(muted); -user_topics.add_muted_topic(general.stream_id, "muted topic"); +user_topics.update_user_topics( + general.stream_id, + "muted topic", + user_topics.all_visibility_policies.MUTED, +); function test(label, f) { run_test(label, (helpers) => { diff --git a/web/tests/settings_muted_topics.test.js b/web/tests/settings_muted_topics.test.js index 9e294ff411..c2079655e5 100644 --- a/web/tests/settings_muted_topics.test.js +++ b/web/tests/settings_muted_topics.test.js @@ -21,7 +21,12 @@ const frontend = { stream_data.add_sub(frontend); run_test("settings", ({override}) => { - user_topics.add_muted_topic(frontend.stream_id, "js", 1577836800); + user_topics.update_user_topics( + frontend.stream_id, + "js", + user_topics.all_visibility_policies.MUTED, + 1577836800, + ); let populate_list_called = false; override(list_widget, "create", ($container, list) => { assert.deepEqual(list, [ diff --git a/web/tests/unread.test.js b/web/tests/unread.test.js index 9558d7ee4b..6bc15824bf 100644 --- a/web/tests/unread.test.js +++ b/web/tests/unread.test.js @@ -233,7 +233,11 @@ test("muting", () => { assert.deepEqual(unread.get_msg_ids_for_stream(stream_id), [message.id]); test_notifiable_count(counts.home_unread_messages, 0); - user_topics.add_muted_topic(social.stream_id, "test_muting"); + user_topics.update_user_topics( + social.stream_id, + "test_muting", + user_topics.all_visibility_policies.MUTED, + ); counts = unread.get_counts(); assert.equal(counts.stream_count.get(stream_id), 0); assert.equal(counts.home_unread_messages, 0); @@ -470,7 +474,7 @@ test("mentions", () => { const muted_stream_id = 401; - user_topics.add_muted_topic(401, "lunch"); + user_topics.update_user_topics(401, "lunch", user_topics.all_visibility_policies.MUTED); const already_read_message = { id: 14, @@ -593,7 +597,7 @@ test("mention updates", () => { test("stream_has_any_unread_mentions", () => { const muted_stream_id = 401; - user_topics.add_muted_topic(401, "lunch"); + user_topics.update_user_topics(401, "lunch", user_topics.all_visibility_policies.MUTED); const mention_me_message = { id: 15, diff --git a/web/tests/user_topics.test.js b/web/tests/user_topics.test.js index 9318052c16..13e26625f4 100644 --- a/web/tests/user_topics.test.js +++ b/web/tests/user_topics.test.js @@ -56,29 +56,60 @@ test("edge_cases", () => { test("add_and_remove_mutes", () => { assert.ok(!user_topics.is_topic_muted(devel.stream_id, "java")); - user_topics.add_muted_topic(devel.stream_id, "java"); + user_topics.update_user_topics(devel.stream_id, "java", all_visibility_policies.MUTED); assert.ok(user_topics.is_topic_muted(devel.stream_id, "java")); // test idempotency - user_topics.add_muted_topic(devel.stream_id, "java"); + user_topics.update_user_topics(devel.stream_id, "java", all_visibility_policies.MUTED); assert.ok(user_topics.is_topic_muted(devel.stream_id, "java")); - user_topics.remove_muted_topic(devel.stream_id, "java"); + user_topics.update_user_topics(devel.stream_id, "java", all_visibility_policies.INHERIT); assert.ok(!user_topics.is_topic_muted(devel.stream_id, "java")); // test idempotency - user_topics.remove_muted_topic(devel.stream_id, "java"); + user_topics.update_user_topics(devel.stream_id, "java", all_visibility_policies.INHERIT); assert.ok(!user_topics.is_topic_muted(devel.stream_id, "java")); // test unknown stream is harmless too - user_topics.remove_muted_topic(unknown.stream_id, "java"); + user_topics.update_user_topics(unknown.stream_id, "java", all_visibility_policies.INHERIT); assert.ok(!user_topics.is_topic_muted(unknown.stream_id, "java")); }); +test("add_and_remove_unmutes", () => { + assert.ok(!user_topics.is_topic_unmuted(devel.stream_id, "java")); + user_topics.update_user_topics(devel.stream_id, "java", all_visibility_policies.UNMUTED); + assert.ok(user_topics.is_topic_unmuted(devel.stream_id, "java")); + + // test idempotency + user_topics.update_user_topics(devel.stream_id, "java", all_visibility_policies.UNMUTED); + assert.ok(user_topics.is_topic_unmuted(devel.stream_id, "java")); + + user_topics.update_user_topics(devel.stream_id, "java", all_visibility_policies.INHERIT); + assert.ok(!user_topics.is_topic_unmuted(devel.stream_id, "java")); + + // test idempotency + user_topics.update_user_topics(devel.stream_id, "java", all_visibility_policies.INHERIT); + assert.ok(!user_topics.is_topic_unmuted(devel.stream_id, "java")); + + // test unknown stream is harmless too + user_topics.update_user_topics(unknown.stream_id, "java", all_visibility_policies.INHERIT); + assert.ok(!user_topics.is_topic_unmuted(unknown.stream_id, "java")); +}); + test("get_mutes", () => { assert.deepEqual(user_topics.get_muted_topics(), []); - user_topics.add_muted_topic(office.stream_id, "gossip", 1577836800); - user_topics.add_muted_topic(devel.stream_id, "java", 1577836700); + user_topics.update_user_topics( + office.stream_id, + "gossip", + all_visibility_policies.MUTED, + 1577836800, + ); + user_topics.update_user_topics( + devel.stream_id, + "java", + all_visibility_policies.MUTED, + 1577836700, + ); const all_muted_topics = user_topics .get_muted_topics() .sort((a, b) => a.date_muted - b.date_muted);