").html(message.content);
+ ui_util.replace_emoji_with_text($content);
+ spoilers.hide_spoilers_in_notification($content);
+
+ if (
+ $content.text().trim() === "" &&
+ (message_parser.message_has_image(message) ||
+ message_parser.message_has_attachment(message))
+ ) {
+ content = $t({defaultMessage: "(attached file)"});
+ } else {
+ content = $content.text();
+ }
+
+ if (message.is_me_message) {
+ content = message.sender_full_name + content.slice(3);
+ }
+
+ if (
+ (message.type === "private" || message.type === "test-notification") &&
+ !user_settings.pm_content_in_desktop_notifications
+ ) {
+ content = "New direct message from " + message.sender_full_name;
+ }
+
+ if (content.length > 150) {
+ let i;
+ // Truncate content at a word boundary
+ for (i = 150; i > 0; i -= 1) {
+ if (content[i] === " ") {
+ break;
+ }
+ }
+ content = content.slice(0, i);
+ content += " [...]";
+ }
+
+ return content;
+}
+
+function debug_notification_source_value(message) {
+ let notification_source;
+
+ if (message.type === "private" || message.type === "test-notification") {
+ notification_source = "pm";
+ } else if (message.mentioned) {
+ notification_source = "mention";
+ } else if (message.alerted) {
+ notification_source = "alert";
+ } else {
+ notification_source = "stream";
+ }
+
+ blueslip.debug("Desktop notification from source " + notification_source);
+}
+
+function get_notification_key(message) {
+ let key;
+
+ if (message.type === "private" || message.type === "test-notification") {
+ key = message.display_reply_to;
+ } else {
+ const stream_name = stream_data.get_stream_name_from_id(message.stream_id);
+ key = message.sender_full_name + " to " + stream_name + " > " + message.topic;
+ }
+
+ return key;
+}
+
+function remove_sender_from_list_of_recipients(message) {
+ return `, ${message.display_reply_to}, `
+ .replace(`, ${message.sender_full_name}, `, ", ")
+ .slice(", ".length, -", ".length);
+}
+
+function get_notification_title(message, content, msg_count) {
+ let title = message.sender_full_name;
+ let other_recipients;
+
+ if (msg_count > 1) {
+ title = msg_count + " messages from " + title;
+ }
+
+ switch (message.type) {
+ case "test-notification":
+ other_recipients = remove_sender_from_list_of_recipients(message);
+ break;
+ case "private":
+ other_recipients = remove_sender_from_list_of_recipients(message);
+ if (message.display_recipient.length > 2) {
+ // If the message has too many recipients to list them all...
+ if (content.length + title.length + other_recipients.length > 230) {
+ // Then count how many people are in the conversation and summarize
+ // by saying the conversation is with "you and [number] other people"
+ other_recipients =
+ other_recipients.replaceAll(/[^,]/g, "").length + " other people";
+ }
+
+ title += " (to you and " + other_recipients + ")";
+ } else {
+ title += " (to you)";
+ }
+ break;
+ case "stream": {
+ const stream_name = stream_data.get_stream_name_from_id(message.stream_id);
+ title += " (to " + stream_name + " > " + message.topic + ")";
+ break;
+ }
+ }
+
+ return title;
+}
+
+export function process_notification(notification) {
+ const message = notification.message;
+ const content = get_notification_content(message);
+ const key = get_notification_key(message);
+ let notification_object;
+ let msg_count = 1;
+
+ debug_notification_source_value(message);
+
+ if (notifications.notice_memory.has(key)) {
+ msg_count = notifications.notice_memory.get(key).msg_count + 1;
+ notification_object = notifications.notice_memory.get(key).obj;
+ notification_object.close();
+ }
+
+ const title = get_notification_title(message, content, msg_count);
+
+ if (notification.desktop_notify) {
+ const icon_url = people.small_avatar_url(message);
+ notification_object = new notifications.NotificationAPI(title, {
+ icon: icon_url,
+ body: content,
+ tag: message.id,
+ });
+ notifications.notice_memory.set(key, {
+ obj: notification_object,
+ msg_count,
+ message_id: message.id,
+ });
+
+ if (typeof notification_object.addEventListener === "function") {
+ // Sadly, some third-party Electron apps like Franz/Ferdi
+ // misimplement the Notification API not inheriting from
+ // EventTarget. This results in addEventListener being
+ // unavailable for them.
+ notification_object.addEventListener("click", () => {
+ notification_object.close();
+ if (message.type !== "test-notification") {
+ narrow.by_topic(message.id, {trigger: "notification"});
+ }
+ window.focus();
+ });
+ notification_object.addEventListener("close", () => {
+ notifications.notice_memory.delete(key);
+ });
+ }
+ }
+}
+
+export function message_is_notifiable(message) {
+ // Independent of the user's notification settings, are there
+ // properties of the message that unconditionally mean we
+ // shouldn't notify about it.
+
+ if (message.sent_by_me) {
+ return false;
+ }
+
+ // If a message is edited multiple times, we want to err on the side of
+ // not spamming notifications.
+ if (message.notification_sent) {
+ return false;
+ }
+
+ // @-
mentions take precedence over muted-ness. Note
+ // that @all mentions are still suppressed by muting.
+ if (message.mentioned_me_directly) {
+ return true;
+ }
+
+ // Messages to followed topics take precedence over muted-ness.
+ if (
+ message.type === "stream" &&
+ user_topics.is_topic_followed(message.stream_id, message.topic)
+ ) {
+ return true;
+ }
+
+ // Messages to unmuted topics in muted streams may generate desktop notifications.
+ if (
+ message.type === "stream" &&
+ stream_data.is_muted(message.stream_id) &&
+ !user_topics.is_topic_unmuted(message.stream_id, message.topic)
+ ) {
+ return false;
+ }
+
+ if (message.type === "stream" && user_topics.is_topic_muted(message.stream_id, message.topic)) {
+ return false;
+ }
+
+ // Everything else is on the table; next filter based on notification
+ // settings.
+ return true;
+}
+
+export function should_send_desktop_notification(message) {
+ // Always notify for testing notifications.
+ if (message.type === "test-notification") {
+ return true;
+ }
+
+ // For streams, send if desktop notifications are enabled for all
+ // message on this stream.
+ if (
+ message.type === "stream" &&
+ stream_data.receives_notifications(message.stream_id, "desktop_notifications")
+ ) {
+ return true;
+ }
+
+ // enable_followed_topic_desktop_notifications determines whether we pop up
+ // a notification for messages in followed topics.
+ if (
+ message.type === "stream" &&
+ user_topics.is_topic_followed(message.stream_id, message.topic) &&
+ user_settings.enable_followed_topic_desktop_notifications
+ ) {
+ return true;
+ }
+
+ // enable_desktop_notifications determines whether we pop up a
+ // notification for direct messages, mentions, and/or alerts.
+ if (!user_settings.enable_desktop_notifications) {
+ return false;
+ }
+
+ // And then we need to check if the message is a direct message,
+ // mention, wildcard mention with wildcard_mentions_notify, or alert.
+ if (message.type === "private") {
+ return true;
+ }
+
+ if (alert_words.notifies(message)) {
+ return true;
+ }
+
+ if (message.mentioned_me_directly) {
+ return true;
+ }
+
+ // The following blocks for 'wildcard mentions' and 'Followed topic wildcard mentions'
+ // should be placed below (as they are right now) the 'user_settings.enable_desktop_notifications'
+ // block because the global, stream-specific, and followed topic wildcard mention
+ // settings are wrappers around the personal-mention setting.
+ // wildcard mentions
+ if (
+ message.mentioned &&
+ stream_data.receives_notifications(message.stream_id, "wildcard_mentions_notify")
+ ) {
+ return true;
+ }
+
+ // Followed topic wildcard mentions
+ if (
+ message.mentioned &&
+ user_topics.is_topic_followed(message.stream_id, message.topic) &&
+ user_settings.enable_followed_topic_wildcard_mentions_notify
+ ) {
+ return true;
+ }
+
+ return false;
+}
+
+export function should_send_audible_notification(message) {
+ // If `None` is selected as the notification sound, never send
+ // audible notifications regardless of other configuration.
+ if (user_settings.notification_sound === "none") {
+ return false;
+ }
+
+ // For streams, ding if sounds are enabled for all messages on
+ // this stream.
+ if (
+ message.type === "stream" &&
+ stream_data.receives_notifications(message.stream_id, "audible_notifications")
+ ) {
+ return true;
+ }
+
+ // enable_followed_topic_audible_notifications determines whether we ding
+ // for messages in followed topics.
+ if (
+ message.type === "stream" &&
+ user_topics.is_topic_followed(message.stream_id, message.topic) &&
+ user_settings.enable_followed_topic_audible_notifications
+ ) {
+ return true;
+ }
+
+ // enable_sounds determines whether we ding for direct messages,
+ // mentions, and/or alerts.
+ if (!user_settings.enable_sounds) {
+ return false;
+ }
+
+ // And then we need to check if the message is a direct message,
+ // mention, wildcard mention with wildcard_mentions_notify, or alert.
+ if (message.type === "private" || message.type === "test-notification") {
+ return true;
+ }
+
+ if (alert_words.notifies(message)) {
+ return true;
+ }
+
+ if (message.mentioned_me_directly) {
+ return true;
+ }
+
+ // The following blocks for 'wildcard mentions' and 'Followed topic wildcard mentions'
+ // should be placed below (as they are right now) the 'user_settings.enable_sounds'
+ // block because the global, stream-specific, and followed topic wildcard mention
+ // settings are wrappers around the personal-mention setting.
+ // wildcard mentions
+ if (
+ message.mentioned &&
+ stream_data.receives_notifications(message.stream_id, "wildcard_mentions_notify")
+ ) {
+ return true;
+ }
+
+ // Followed topic wildcard mentions
+ if (
+ message.mentioned &&
+ user_topics.is_topic_followed(message.stream_id, message.topic) &&
+ user_settings.enable_followed_topic_wildcard_mentions_notify
+ ) {
+ return true;
+ }
+
+ return false;
+}
+
+export function received_messages(messages) {
+ for (const message of messages) {
+ if (!message_is_notifiable(message)) {
+ continue;
+ }
+ if (!unread.message_unread(message)) {
+ // The message is already read; Zulip is currently in focus.
+ continue;
+ }
+
+ message.notification_sent = true;
+
+ if (should_send_desktop_notification(message)) {
+ process_notification({
+ message,
+ desktop_notify: notifications.granted_desktop_notifications_permission(),
+ });
+ }
+ if (should_send_audible_notification(message)) {
+ ui_util.play_audio($("#user-notification-sound-audio")[0]);
+ }
+ }
+}
+
+export function send_test_notification(content) {
+ received_messages([
+ {
+ id: Math.random(),
+ type: "test-notification",
+ sender_email: "notification-bot@zulip.com",
+ sender_full_name: "Notification Bot",
+ display_reply_to: "Notification Bot",
+ content,
+ unread: true,
+ },
+ ]);
+}
diff --git a/web/src/notifications.js b/web/src/notifications.js
index 6c993b1c5a..cf5a7753e4 100644
--- a/web/src/notifications.js
+++ b/web/src/notifications.js
@@ -3,26 +3,21 @@ import $ from "jquery";
import render_message_sent_banner from "../templates/compose_banner/message_sent_banner.hbs";
import render_unmute_topic_banner from "../templates/compose_banner/unmute_topic_banner.hbs";
-import * as alert_words from "./alert_words";
import * as blueslip from "./blueslip";
import * as compose_banner from "./compose_banner";
import * as hash_util from "./hash_util";
import {$t} from "./i18n";
import * as message_lists from "./message_lists";
-import * as message_parser from "./message_parser";
import * as narrow from "./narrow";
import * as narrow_state from "./narrow_state";
import * as people from "./people";
-import * as spoilers from "./spoilers";
import * as stream_data from "./stream_data";
-import * as ui_util from "./ui_util";
-import * as unread from "./unread";
import {user_settings} from "./user_settings";
import * as user_topics from "./user_topics";
-const notice_memory = new Map();
+export const notice_memory = new Map();
-let NotificationAPI;
+export let NotificationAPI;
export function set_notification_api(n) {
NotificationAPI = n;
@@ -140,171 +135,6 @@ export function notify_above_composebox(
compose_banner.append_compose_banner_to_banner_list($notification, $("#compose_banners"));
}
-function get_notification_content(message) {
- let content;
- // Convert the content to plain text, replacing emoji with their alt text
- const $content = $("").html(message.content);
- ui_util.replace_emoji_with_text($content);
- spoilers.hide_spoilers_in_notification($content);
-
- if (
- $content.text().trim() === "" &&
- (message_parser.message_has_image(message) ||
- message_parser.message_has_attachment(message))
- ) {
- content = $t({defaultMessage: "(attached file)"});
- } else {
- content = $content.text();
- }
-
- if (message.is_me_message) {
- content = message.sender_full_name + content.slice(3);
- }
-
- if (
- (message.type === "private" || message.type === "test-notification") &&
- !user_settings.pm_content_in_desktop_notifications
- ) {
- content = "New direct message from " + message.sender_full_name;
- }
-
- if (content.length > 150) {
- let i;
- // Truncate content at a word boundary
- for (i = 150; i > 0; i -= 1) {
- if (content[i] === " ") {
- break;
- }
- }
- content = content.slice(0, i);
- content += " [...]";
- }
-
- return content;
-}
-
-function debug_notification_source_value(message) {
- let notification_source;
-
- if (message.type === "private" || message.type === "test-notification") {
- notification_source = "pm";
- } else if (message.mentioned) {
- notification_source = "mention";
- } else if (message.alerted) {
- notification_source = "alert";
- } else {
- notification_source = "stream";
- }
-
- blueslip.debug("Desktop notification from source " + notification_source);
-}
-
-function get_notification_key(message) {
- let key;
-
- if (message.type === "private" || message.type === "test-notification") {
- key = message.display_reply_to;
- } else {
- const stream_name = stream_data.get_stream_name_from_id(message.stream_id);
- key = message.sender_full_name + " to " + stream_name + " > " + message.topic;
- }
-
- return key;
-}
-
-function remove_sender_from_list_of_recipients(message) {
- return `, ${message.display_reply_to}, `
- .replace(`, ${message.sender_full_name}, `, ", ")
- .slice(", ".length, -", ".length);
-}
-
-function get_notification_title(message, content, msg_count) {
- let title = message.sender_full_name;
- let other_recipients;
-
- if (msg_count > 1) {
- title = msg_count + " messages from " + title;
- }
-
- switch (message.type) {
- case "test-notification":
- other_recipients = remove_sender_from_list_of_recipients(message);
- break;
- case "private":
- other_recipients = remove_sender_from_list_of_recipients(message);
- if (message.display_recipient.length > 2) {
- // If the message has too many recipients to list them all...
- if (content.length + title.length + other_recipients.length > 230) {
- // Then count how many people are in the conversation and summarize
- // by saying the conversation is with "you and [number] other people"
- other_recipients =
- other_recipients.replaceAll(/[^,]/g, "").length + " other people";
- }
-
- title += " (to you and " + other_recipients + ")";
- } else {
- title += " (to you)";
- }
- break;
- case "stream": {
- const stream_name = stream_data.get_stream_name_from_id(message.stream_id);
- title += " (to " + stream_name + " > " + message.topic + ")";
- break;
- }
- }
-
- return title;
-}
-
-export function process_notification(notification) {
- const message = notification.message;
- const content = get_notification_content(message);
- const key = get_notification_key(message);
- let notification_object;
- let msg_count = 1;
-
- debug_notification_source_value(message);
-
- if (notice_memory.has(key)) {
- msg_count = notice_memory.get(key).msg_count + 1;
- notification_object = notice_memory.get(key).obj;
- notification_object.close();
- }
-
- const title = get_notification_title(message, content, msg_count);
-
- if (notification.desktop_notify) {
- const icon_url = people.small_avatar_url(message);
- notification_object = new NotificationAPI(title, {
- icon: icon_url,
- body: content,
- tag: message.id,
- });
- notice_memory.set(key, {
- obj: notification_object,
- msg_count,
- message_id: message.id,
- });
-
- if (typeof notification_object.addEventListener === "function") {
- // Sadly, some third-party Electron apps like Franz/Ferdi
- // misimplement the Notification API not inheriting from
- // EventTarget. This results in addEventListener being
- // unavailable for them.
- notification_object.addEventListener("click", () => {
- notification_object.close();
- if (message.type !== "test-notification") {
- narrow.by_topic(message.id, {trigger: "notification"});
- }
- window.focus();
- });
- notification_object.addEventListener("close", () => {
- notice_memory.delete(key);
- });
- }
- }
-}
-
export function close_notification(message) {
for (const [key, notice_mem_entry] of notice_memory) {
if (notice_mem_entry.message_id === message.id) {
@@ -314,192 +144,6 @@ export function close_notification(message) {
}
}
-export function message_is_notifiable(message) {
- // Independent of the user's notification settings, are there
- // properties of the message that unconditionally mean we
- // shouldn't notify about it.
-
- if (message.sent_by_me) {
- return false;
- }
-
- // If a message is edited multiple times, we want to err on the side of
- // not spamming notifications.
- if (message.notification_sent) {
- return false;
- }
-
- // @- mentions take precedence over muted-ness. Note
- // that @all mentions are still suppressed by muting.
- if (message.mentioned_me_directly) {
- return true;
- }
-
- // Messages to followed topics take precedence over muted-ness.
- if (
- message.type === "stream" &&
- user_topics.is_topic_followed(message.stream_id, message.topic)
- ) {
- return true;
- }
-
- // Messages to unmuted topics in muted streams may generate desktop notifications.
- if (
- message.type === "stream" &&
- stream_data.is_muted(message.stream_id) &&
- !user_topics.is_topic_unmuted(message.stream_id, message.topic)
- ) {
- return false;
- }
-
- if (message.type === "stream" && user_topics.is_topic_muted(message.stream_id, message.topic)) {
- return false;
- }
-
- // Everything else is on the table; next filter based on notification
- // settings.
- return true;
-}
-
-export function should_send_desktop_notification(message) {
- // Always notify for testing notifications.
- if (message.type === "test-notification") {
- return true;
- }
-
- // For streams, send if desktop notifications are enabled for all
- // message on this stream.
- if (
- message.type === "stream" &&
- stream_data.receives_notifications(message.stream_id, "desktop_notifications")
- ) {
- return true;
- }
-
- // enable_followed_topic_desktop_notifications determines whether we pop up
- // a notification for messages in followed topics.
- if (
- message.type === "stream" &&
- user_topics.is_topic_followed(message.stream_id, message.topic) &&
- user_settings.enable_followed_topic_desktop_notifications
- ) {
- return true;
- }
-
- // enable_desktop_notifications determines whether we pop up a
- // notification for direct messages, mentions, and/or alerts.
- if (!user_settings.enable_desktop_notifications) {
- return false;
- }
-
- // And then we need to check if the message is a direct message,
- // mention, wildcard mention with wildcard_mentions_notify, or alert.
- if (message.type === "private") {
- return true;
- }
-
- if (alert_words.notifies(message)) {
- return true;
- }
-
- if (message.mentioned_me_directly) {
- return true;
- }
-
- // The following blocks for 'wildcard mentions' and 'Followed topic wildcard mentions'
- // should be placed below (as they are right now) the 'user_settings.enable_desktop_notifications'
- // block because the global, stream-specific, and followed topic wildcard mention
- // settings are wrappers around the personal-mention setting.
- // wildcard mentions
- if (
- message.mentioned &&
- stream_data.receives_notifications(message.stream_id, "wildcard_mentions_notify")
- ) {
- return true;
- }
-
- // Followed topic wildcard mentions
- if (
- message.mentioned &&
- user_topics.is_topic_followed(message.stream_id, message.topic) &&
- user_settings.enable_followed_topic_wildcard_mentions_notify
- ) {
- return true;
- }
-
- return false;
-}
-
-export function should_send_audible_notification(message) {
- // If `None` is selected as the notification sound, never send
- // audible notifications regardless of other configuration.
- if (user_settings.notification_sound === "none") {
- return false;
- }
-
- // For streams, ding if sounds are enabled for all messages on
- // this stream.
- if (
- message.type === "stream" &&
- stream_data.receives_notifications(message.stream_id, "audible_notifications")
- ) {
- return true;
- }
-
- // enable_followed_topic_audible_notifications determines whether we ding
- // for messages in followed topics.
- if (
- message.type === "stream" &&
- user_topics.is_topic_followed(message.stream_id, message.topic) &&
- user_settings.enable_followed_topic_audible_notifications
- ) {
- return true;
- }
-
- // enable_sounds determines whether we ding for direct messages,
- // mentions, and/or alerts.
- if (!user_settings.enable_sounds) {
- return false;
- }
-
- // And then we need to check if the message is a direct message,
- // mention, wildcard mention with wildcard_mentions_notify, or alert.
- if (message.type === "private" || message.type === "test-notification") {
- return true;
- }
-
- if (alert_words.notifies(message)) {
- return true;
- }
-
- if (message.mentioned_me_directly) {
- return true;
- }
-
- // The following blocks for 'wildcard mentions' and 'Followed topic wildcard mentions'
- // should be placed below (as they are right now) the 'user_settings.enable_sounds'
- // block because the global, stream-specific, and followed topic wildcard mention
- // settings are wrappers around the personal-mention setting.
- // wildcard mentions
- if (
- message.mentioned &&
- stream_data.receives_notifications(message.stream_id, "wildcard_mentions_notify")
- ) {
- return true;
- }
-
- // Followed topic wildcard mentions
- if (
- message.mentioned &&
- user_topics.is_topic_followed(message.stream_id, message.topic) &&
- user_settings.enable_followed_topic_wildcard_mentions_notify
- ) {
- return true;
- }
-
- return false;
-}
-
export function granted_desktop_notifications_permission() {
return NotificationAPI && NotificationAPI.permission === "granted";
}
@@ -510,44 +154,6 @@ export function request_desktop_notifications_permission() {
}
}
-export function received_messages(messages) {
- for (const message of messages) {
- if (!message_is_notifiable(message)) {
- continue;
- }
- if (!unread.message_unread(message)) {
- // The message is already read; Zulip is currently in focus.
- continue;
- }
-
- message.notification_sent = true;
-
- if (should_send_desktop_notification(message)) {
- process_notification({
- message,
- desktop_notify: granted_desktop_notifications_permission(),
- });
- }
- if (should_send_audible_notification(message)) {
- ui_util.play_audio($("#user-notification-sound-audio")[0]);
- }
- }
-}
-
-export function send_test_notification(content) {
- received_messages([
- {
- id: Math.random(),
- type: "test-notification",
- sender_email: "notification-bot@zulip.com",
- sender_full_name: "Notification Bot",
- display_reply_to: "Notification Bot",
- content,
- unread: true,
- },
- ]);
-}
-
// Note that this returns values that are not HTML-escaped, for use in
// Handlebars templates that will do further escaping.
function get_message_header(message) {
@@ -736,13 +342,13 @@ export function reify_message_id(opts) {
}
}
-function register_click_handlers({on_click_scroll_to_selected}) {
+export function register_click_handlers({on_click_scroll_to_selected}) {
$("#compose_banners").on(
"click",
".narrow_to_recipient .above_compose_banner_action_link",
(e) => {
const message_id = $(e.currentTarget).data("message-id");
- narrow.by_topic(message_id, {trigger: "compose_notification"});
+ narrow.by_topic(message_id, {trigger: "notification"});
e.stopPropagation();
e.preventDefault();
},
diff --git a/web/src/settings_notifications.js b/web/src/settings_notifications.js
index 4713cecd9a..43a3c816d9 100644
--- a/web/src/settings_notifications.js
+++ b/web/src/settings_notifications.js
@@ -7,7 +7,7 @@ import * as blueslip from "./blueslip";
import * as channel from "./channel";
import * as confirm_dialog from "./confirm_dialog";
import {$t, $t_html} from "./i18n";
-import * as notifications from "./notifications";
+import * as message_notifications from "./message_notifications";
import {page_params} from "./page_params";
import * as settings_config from "./settings_config";
import * as settings_org from "./settings_org";
@@ -280,7 +280,7 @@ export function set_up(settings_panel) {
// intentionally don't let organization administrators set
// organization-level defaults.
$container.find(".send_test_notification").on("click", () => {
- notifications.send_test_notification(
+ message_notifications.send_test_notification(
$t({defaultMessage: "This is what a Zulip notification looks like."}),
);
});
diff --git a/web/tests/example5.test.js b/web/tests/example5.test.js
index 74702dfade..4ebbaf3ec9 100644
--- a/web/tests/example5.test.js
+++ b/web/tests/example5.test.js
@@ -22,8 +22,8 @@ const {run_test} = require("./lib/test");
// replace them with {}.
const huddle_data = mock_esm("../src/huddle_data");
const message_lists = mock_esm("../src/message_lists");
+const message_notifications = mock_esm("../src/message_notifications");
const message_util = mock_esm("../src/message_util");
-const notifications = mock_esm("../src/notifications");
const pm_list = mock_esm("../src/pm_list");
const recent_view_data = mock_esm("../src/recent_view_data");
const stream_list = mock_esm("../src/stream_list");
@@ -99,9 +99,9 @@ run_test("insert_message", ({override}) => {
assert.equal(message_store.get(new_message.id), undefined);
helper.redirect(huddle_data, "process_loaded_messages");
+ helper.redirect(message_notifications, "received_messages");
helper.redirect(message_util, "add_new_messages_data");
helper.redirect(message_util, "add_new_messages");
- helper.redirect(notifications, "received_messages");
helper.redirect(recent_view_data, "process_message");
helper.redirect(stream_list, "update_streams_sidebar");
helper.redirect(unread_ops, "process_visible");
@@ -122,7 +122,7 @@ run_test("insert_message", ({override}) => {
[message_util, "add_new_messages"],
[unread_ui, "update_unread_counts"],
[unread_ops, "process_visible"],
- [notifications, "received_messages"],
+ [message_notifications, "received_messages"],
[stream_list, "update_streams_sidebar"],
[recent_view_data, "process_message"],
]);
diff --git a/web/tests/message_events.test.js b/web/tests/message_events.test.js
index 073c982e50..8cde765ce2 100644
--- a/web/tests/message_events.test.js
+++ b/web/tests/message_events.test.js
@@ -9,7 +9,7 @@ const {page_params} = require("./lib/zpage_params");
const message_edit = mock_esm("../src/message_edit");
const message_lists = mock_esm("../src/message_lists");
-const notifications = mock_esm("../src/notifications");
+const message_notifications = mock_esm("../src/message_notifications");
const pm_list = mock_esm("../src/pm_list");
const stream_list = mock_esm("../src/stream_list");
const unread_ui = mock_esm("../src/unread_ui");
@@ -99,7 +99,7 @@ run_test("update_messages", () => {
const side_effects = [
[message_edit, "end_message_edit"],
- [notifications, "received_messages"],
+ [message_notifications, "received_messages"],
[unread_ui, "update_unread_counts"],
[stream_list, "update_streams_sidebar"],
[pm_list, "update_private_messages"],
diff --git a/web/tests/notifications.test.js b/web/tests/notifications.test.js
index ee8c569fbd..00e2b3b884 100644
--- a/web/tests/notifications.test.js
+++ b/web/tests/notifications.test.js
@@ -13,6 +13,7 @@ const user_topics = zrequire("user_topics");
const stream_data = zrequire("stream_data");
const notifications = zrequire("notifications");
+const message_notifications = zrequire("message_notifications");
// Not muted streams
const general = {
@@ -82,10 +83,10 @@ test("message_is_notifiable", () => {
stream_id: general.stream_id,
topic: "whatever",
};
- assert.equal(notifications.should_send_desktop_notification(message), true);
- assert.equal(notifications.should_send_audible_notification(message), true);
+ assert.equal(message_notifications.should_send_desktop_notification(message), true);
+ assert.equal(message_notifications.should_send_audible_notification(message), true);
// Not notifiable because it was sent by the current user
- assert.equal(notifications.message_is_notifiable(message), false);
+ assert.equal(message_notifications.message_is_notifiable(message), false);
// Case 2: If the user has already been sent a notification about this message,
// DO NOT notify the user
@@ -103,9 +104,9 @@ test("message_is_notifiable", () => {
stream_id: general.stream_id,
topic: "whatever",
};
- assert.equal(notifications.should_send_desktop_notification(message), true);
- assert.equal(notifications.should_send_audible_notification(message), true);
- assert.equal(notifications.message_is_notifiable(message), false);
+ assert.equal(message_notifications.should_send_desktop_notification(message), true);
+ assert.equal(message_notifications.should_send_audible_notification(message), true);
+ assert.equal(message_notifications.message_is_notifiable(message), false);
// Case 3: If a message mentions the user directly,
// DO notify the user
@@ -121,9 +122,9 @@ test("message_is_notifiable", () => {
stream_id: muted.stream_id,
topic: "topic_three",
};
- assert.equal(notifications.should_send_desktop_notification(message), true);
- assert.equal(notifications.should_send_audible_notification(message), true);
- assert.equal(notifications.message_is_notifiable(message), true);
+ assert.equal(message_notifications.should_send_desktop_notification(message), true);
+ assert.equal(message_notifications.should_send_audible_notification(message), true);
+ assert.equal(message_notifications.message_is_notifiable(message), true);
// Case 4: If the message has been sent to a followed topic,
// DO visually and audibly notify the user if 'enable_followed_topic_desktop_notifications'
@@ -140,17 +141,17 @@ test("message_is_notifiable", () => {
stream_id: general.stream_id,
topic: "followed topic",
};
- assert.equal(notifications.should_send_desktop_notification(message), true);
- assert.equal(notifications.should_send_audible_notification(message), true);
- assert.equal(notifications.message_is_notifiable(message), true);
+ assert.equal(message_notifications.should_send_desktop_notification(message), true);
+ assert.equal(message_notifications.should_send_audible_notification(message), true);
+ assert.equal(message_notifications.message_is_notifiable(message), true);
// But not if 'enable_followed_topic_desktop_notifications'
// and 'enable_followed_topic_audible_notifications' are disabled.
user_settings.enable_followed_topic_desktop_notifications = false;
user_settings.enable_followed_topic_audible_notifications = false;
- assert.equal(notifications.should_send_desktop_notification(message), false);
- assert.equal(notifications.should_send_audible_notification(message), false);
- assert.equal(notifications.message_is_notifiable(message), true);
+ assert.equal(message_notifications.should_send_desktop_notification(message), false);
+ assert.equal(message_notifications.should_send_audible_notification(message), false);
+ assert.equal(message_notifications.message_is_notifiable(message), true);
// Reset state
user_settings.enable_followed_topic_desktop_notifications = true;
@@ -168,9 +169,9 @@ test("message_is_notifiable", () => {
stream_id: general.stream_id,
topic: "vanilla",
};
- assert.equal(notifications.should_send_desktop_notification(message), true);
- assert.equal(notifications.should_send_audible_notification(message), true);
- assert.equal(notifications.message_is_notifiable(message), true);
+ assert.equal(message_notifications.should_send_desktop_notification(message), true);
+ assert.equal(message_notifications.should_send_audible_notification(message), true);
+ assert.equal(message_notifications.message_is_notifiable(message), true);
// Case 6:
// Wildcard mention should trigger notification in unmuted topic
@@ -186,21 +187,21 @@ test("message_is_notifiable", () => {
stream_id: general.stream_id,
topic: "vanilla",
};
- assert.equal(notifications.should_send_desktop_notification(message), true);
- assert.equal(notifications.should_send_audible_notification(message), true);
- assert.equal(notifications.message_is_notifiable(message), true);
+ assert.equal(message_notifications.should_send_desktop_notification(message), true);
+ assert.equal(message_notifications.should_send_audible_notification(message), true);
+ assert.equal(message_notifications.message_is_notifiable(message), true);
// But not if it's disabled
user_settings.wildcard_mentions_notify = false;
- assert.equal(notifications.should_send_desktop_notification(message), false);
- assert.equal(notifications.should_send_audible_notification(message), false);
- assert.equal(notifications.message_is_notifiable(message), true);
+ assert.equal(message_notifications.should_send_desktop_notification(message), false);
+ assert.equal(message_notifications.should_send_audible_notification(message), false);
+ assert.equal(message_notifications.message_is_notifiable(message), true);
// And the stream-level setting overrides the global setting
general.wildcard_mentions_notify = true;
- assert.equal(notifications.should_send_desktop_notification(message), true);
- assert.equal(notifications.should_send_audible_notification(message), true);
- assert.equal(notifications.message_is_notifiable(message), true);
+ assert.equal(message_notifications.should_send_desktop_notification(message), true);
+ assert.equal(message_notifications.should_send_audible_notification(message), true);
+ assert.equal(message_notifications.message_is_notifiable(message), true);
// Reset state
user_settings.wildcard_mentions_notify = true;
@@ -220,9 +221,9 @@ test("message_is_notifiable", () => {
stream_id: muted.stream_id,
topic: "whatever",
};
- assert.equal(notifications.should_send_desktop_notification(message), true);
- assert.equal(notifications.should_send_audible_notification(message), true);
- assert.equal(notifications.message_is_notifiable(message), false);
+ assert.equal(message_notifications.should_send_desktop_notification(message), true);
+ assert.equal(message_notifications.should_send_audible_notification(message), true);
+ assert.equal(message_notifications.message_is_notifiable(message), false);
// Case 8: If a message is in a muted stream
// and does mention the user DIRECTLY,
@@ -238,9 +239,9 @@ test("message_is_notifiable", () => {
stream_id: muted.stream_id,
topic: "whatever",
};
- assert.equal(notifications.should_send_desktop_notification(message), true);
- assert.equal(notifications.should_send_audible_notification(message), true);
- assert.equal(notifications.message_is_notifiable(message), true);
+ assert.equal(message_notifications.should_send_desktop_notification(message), true);
+ assert.equal(message_notifications.should_send_audible_notification(message), true);
+ assert.equal(message_notifications.message_is_notifiable(message), true);
// Case 9: If a message is in a muted topic
// and does not mention the user DIRECTLY (i.e. wildcard mention),
@@ -256,9 +257,9 @@ test("message_is_notifiable", () => {
stream_id: general.stream_id,
topic: "muted topic",
};
- assert.equal(notifications.should_send_desktop_notification(message), true);
- assert.equal(notifications.should_send_audible_notification(message), true);
- assert.equal(notifications.message_is_notifiable(message), false);
+ assert.equal(message_notifications.should_send_desktop_notification(message), true);
+ assert.equal(message_notifications.should_send_audible_notification(message), true);
+ assert.equal(message_notifications.message_is_notifiable(message), false);
// Case 10:
// Wildcard mentions in a followed topic with 'wildcard_mentions_notify',
@@ -280,15 +281,15 @@ test("message_is_notifiable", () => {
stream_id: general.stream_id,
topic: "followed topic",
};
- assert.equal(notifications.should_send_desktop_notification(message), true);
- assert.equal(notifications.should_send_audible_notification(message), true);
- assert.equal(notifications.message_is_notifiable(message), true);
+ assert.equal(message_notifications.should_send_desktop_notification(message), true);
+ assert.equal(message_notifications.should_send_audible_notification(message), true);
+ assert.equal(message_notifications.message_is_notifiable(message), true);
// But not if 'enable_followed_topic_wildcard_mentions_notify' is disabled
user_settings.enable_followed_topic_wildcard_mentions_notify = false;
- assert.equal(notifications.should_send_desktop_notification(message), false);
- assert.equal(notifications.should_send_audible_notification(message), false);
- assert.equal(notifications.message_is_notifiable(message), true);
+ assert.equal(message_notifications.should_send_desktop_notification(message), false);
+ assert.equal(message_notifications.should_send_audible_notification(message), false);
+ assert.equal(message_notifications.message_is_notifiable(message), true);
// Reset state
user_settings.wildcard_mentions_notify = true;
@@ -310,9 +311,9 @@ test("message_is_notifiable", () => {
topic: "whatever",
};
user_settings.notification_sound = "none";
- assert.equal(notifications.should_send_desktop_notification(message), true);
- assert.equal(notifications.should_send_audible_notification(message), false);
- assert.equal(notifications.message_is_notifiable(message), true);
+ assert.equal(message_notifications.should_send_desktop_notification(message), true);
+ assert.equal(message_notifications.should_send_audible_notification(message), false);
+ assert.equal(message_notifications.message_is_notifiable(message), true);
// Reset state
user_settings.notification_sound = "ding";
@@ -332,9 +333,9 @@ test("message_is_notifiable", () => {
stream_id: general.stream_id,
topic: "whatever",
};
- assert.equal(notifications.should_send_desktop_notification(message), false);
- assert.equal(notifications.should_send_audible_notification(message), false);
- assert.equal(notifications.message_is_notifiable(message), true);
+ assert.equal(message_notifications.should_send_desktop_notification(message), false);
+ assert.equal(message_notifications.should_send_audible_notification(message), false);
+ assert.equal(message_notifications.message_is_notifiable(message), true);
});
test("basic_notifications", () => {
@@ -393,7 +394,7 @@ test("basic_notifications", () => {
};
// Send notification.
- notifications.process_notification({message: message_1, desktop_notify: true});
+ message_notifications.process_notification({message: message_1, desktop_notify: true});
n = notifications.get_notifications();
assert.equal(n.has("Jesse Pinkman to general > whatever"), true);
assert.equal(n.size, 1);
@@ -408,7 +409,7 @@ test("basic_notifications", () => {
// Send notification.
message_1.id = 1001;
- notifications.process_notification({message: message_1, desktop_notify: true});
+ message_notifications.process_notification({message: message_1, desktop_notify: true});
n = notifications.get_notifications();
assert.equal(n.has("Jesse Pinkman to general > whatever"), true);
assert.equal(n.size, 1);
@@ -416,14 +417,14 @@ test("basic_notifications", () => {
// Process same message again. Notification count shouldn't increase.
message_1.id = 1002;
- notifications.process_notification({message: message_1, desktop_notify: true});
+ message_notifications.process_notification({message: message_1, desktop_notify: true});
n = notifications.get_notifications();
assert.equal(n.has("Jesse Pinkman to general > whatever"), true);
assert.equal(n.size, 1);
assert.equal(last_shown_message_id, message_1.id);
// Send another message. Notification count should increase.
- notifications.process_notification({message: message_2, desktop_notify: true});
+ message_notifications.process_notification({message: message_2, desktop_notify: true});
n = notifications.get_notifications();
assert.equal(n.has("Gus Fring to general > lunch"), true);
assert.equal(n.has("Jesse Pinkman to general > whatever"), true);