web: Add is:watched alias for search operator.

This commit replaces `is:alerted` with `is:watched` as part of the migration from
alert words to watched phrases.
This commit is contained in:
Aditya Kumar Kasaudhan 2024-11-07 15:38:57 +05:30
parent 1ff669c1d4
commit 46b57e6605
20 changed files with 135 additions and 93 deletions

View File

@ -43,7 +43,7 @@ const alert_regex_replacements = new Map<string, string>([
export function process_message(message: Message): void { export function process_message(message: Message): void {
// Parsing for alert words is expensive, so we rely on the host // Parsing for alert words is expensive, so we rely on the host
// to tell us there any alert words to even look for. // to tell us there any alert words to even look for.
if (!message.alerted) { if (!message.watched) {
return; return;
} }
@ -89,7 +89,7 @@ export function notifies(message: Message): boolean {
// alert words into a message, just because that can be annoying for // alert words into a message, just because that can be annoying for
// certain types of workflows where everybody on your team, including // certain types of workflows where everybody on your team, including
// yourself, sets up an alert word to effectively mention the team. // yourself, sets up an alert word to effectively mention the team.
return !people.is_current_user(message.sender_email) && message.alerted; return !people.is_current_user(message.sender_email) && message.watched;
} }
export const initialize = (params: StateData["alert_words"]): void => { export const initialize = (params: StateData["alert_words"]): void => {

View File

@ -73,7 +73,7 @@ type LocalEditRequest = Partial<{
starred: boolean; starred: boolean;
historical: boolean; historical: boolean;
collapsed: boolean; collapsed: boolean;
alerted: boolean; watched: boolean;
mentioned: boolean; mentioned: boolean;
mentioned_me_directly: boolean; mentioned_me_directly: boolean;
}>; }>;
@ -403,7 +403,7 @@ export function edit_locally(message: Message, request: LocalEditRequest): Messa
message.content = request.content; message.content = request.content;
message.mentioned = request.mentioned ?? false; message.mentioned = request.mentioned ?? false;
message.mentioned_me_directly = request.mentioned_me_directly ?? false; message.mentioned_me_directly = request.mentioned_me_directly ?? false;
message.alerted = request.alerted ?? false; message.watched = request.watched ?? false;
} else { } else {
// Otherwise, we Markdown-render the message; this resets // Otherwise, we Markdown-render the message; this resets
// all flags, so we need to restore those flags that are // all flags, so we need to restore those flags that are

View File

@ -167,8 +167,8 @@ function message_matches_search_term(message: Message, operator: string, operand
return message.starred; return message.starred;
case "mentioned": case "mentioned":
return message.mentioned; return message.mentioned;
case "alerted": case "watched":
return message.alerted; return message.watched;
case "unread": case "unread":
return message.unread; return message.unread;
case "resolved": case "resolved":
@ -553,7 +553,7 @@ export class Filter {
"private", "private",
"starred", "starred",
"mentioned", "mentioned",
"alerted", "watched",
"unread", "unread",
"resolved", "resolved",
"followed", "followed",
@ -646,7 +646,7 @@ export class Filter {
"sender", "sender",
"near", "near",
"id", "id",
"is-alerted", "is-watched",
"is-mentioned", "is-mentioned",
"is-dm", "is-dm",
"is-starred", "is-starred",
@ -1412,8 +1412,8 @@ export class Filter {
// These cases return false for is_common_narrow, and therefore are not // These cases return false for is_common_narrow, and therefore are not
// formatted in the message view header. They are used in narrow.js to // formatted in the message view header. They are used in narrow.js to
// update the browser title. // update the browser title.
case "is-alerted": case "is-watched":
return $t({defaultMessage: "Alerted messages"}); return $t({defaultMessage: "Messages with watched phrases"});
case "is-unread": case "is-unread":
return $t({defaultMessage: "Unread messages"}); return $t({defaultMessage: "Unread messages"});
} }

View File

@ -81,7 +81,7 @@ type EchoedMessageData = {
// These flags are rendering artifacts we'll want if the // These flags are rendering artifacts we'll want if the
// edit fails and we need to revert to the original // edit fails and we need to revert to the original
// rendering of the message. // rendering of the message.
alerted: boolean; watched: boolean;
mentioned: boolean; mentioned: boolean;
mentioned_me_directly: boolean; mentioned_me_directly: boolean;
}; };
@ -1135,7 +1135,7 @@ export function save_message_row_edit($row: JQuery): void {
starred: message.starred, starred: message.starred,
historical: message.historical, historical: message.historical,
collapsed: message.collapsed, collapsed: message.collapsed,
alerted: message.alerted, watched: message.watched,
mentioned: message.mentioned, mentioned: message.mentioned,
mentioned_me_directly: message.mentioned, mentioned_me_directly: message.mentioned,
}); });
@ -1194,7 +1194,7 @@ export function save_message_row_edit($row: JQuery): void {
raw_content: echo_data.orig_raw_content, raw_content: echo_data.orig_raw_content,
mentioned: echo_data.mentioned, mentioned: echo_data.mentioned,
mentioned_me_directly: echo_data.mentioned_me_directly, mentioned_me_directly: echo_data.mentioned_me_directly,
alerted: echo_data.alerted, watched: echo_data.watched,
}); });
$row = message_lists.current.get_row(message_id); $row = message_lists.current.get_row(message_id);

View File

@ -124,7 +124,7 @@ export let update_views_filtered_on_message_property = (
"is-starred", "is-starred",
"is-unread", "is-unread",
"is-mentioned", "is-mentioned",
"is-alerted", "is-watched",
]; ];
if (message_ids.length === 0 || !supported_term_types.includes(property_term_type)) { if (message_ids.length === 0 || !supported_term_types.includes(property_term_type)) {
@ -777,8 +777,8 @@ export function update_messages(events) {
"is-mentioned", "is-mentioned",
is_mentioned, is_mentioned,
); );
const is_alerted = event.flags.includes("has_alert_word"); const is_watched = event.flags.includes("has_alert_word");
update_views_filtered_on_message_property([event.message_id], "is-alerted", is_alerted); update_views_filtered_on_message_property([event.message_id], "is-watched", is_watched);
} }
} }

View File

@ -79,7 +79,7 @@ function debug_notification_source_value(message: Message | TestNotificationMess
notification_source = "pm"; notification_source = "pm";
} else if (message.mentioned) { } else if (message.mentioned) {
notification_source = "mention"; notification_source = "mention";
} else if (message.alerted) { } else if (message.watched) {
notification_source = "alert"; notification_source = "alert";
} else { } else {
notification_source = "stream"; notification_source = "stream";

View File

@ -120,7 +120,7 @@ export type MessageWithBooleans = (
topic_wildcard_mentioned: boolean; topic_wildcard_mentioned: boolean;
collapsed: boolean; collapsed: boolean;
condensed?: boolean; condensed?: boolean;
alerted: boolean; watched: boolean;
}; };
export type MessageCleanReaction = { export type MessageCleanReaction = {
@ -258,7 +258,7 @@ export function convert_raw_message_to_message_with_booleans(
stream_wildcard_mentioned: convert_flag("stream_wildcard_mentioned"), stream_wildcard_mentioned: convert_flag("stream_wildcard_mentioned"),
topic_wildcard_mentioned: convert_flag("topic_wildcard_mentioned"), topic_wildcard_mentioned: convert_flag("topic_wildcard_mentioned"),
collapsed: convert_flag("collapsed"), collapsed: convert_flag("collapsed"),
alerted: convert_flag("has_alert_word"), watched: convert_flag("has_alert_word"),
}; };
// Once we have set boolean flags here, the `flags` attribute is // Once we have set boolean flags here, the `flags` attribute is
@ -294,7 +294,7 @@ export function update_booleans(message: Message, flags: string[]): void {
message.mentioned_me_directly = convert_flag("mentioned"); message.mentioned_me_directly = convert_flag("mentioned");
message.stream_wildcard_mentioned = convert_flag("stream_wildcard_mentioned"); message.stream_wildcard_mentioned = convert_flag("stream_wildcard_mentioned");
message.topic_wildcard_mentioned = convert_flag("topic_wildcard_mentioned"); message.topic_wildcard_mentioned = convert_flag("topic_wildcard_mentioned");
message.alerted = convert_flag("has_alert_word"); message.watched = convert_flag("has_alert_word");
} }
export function update_sender_full_name(user_id: number, new_name: string): void { export function update_sender_full_name(user_id: number, new_name: string): void {

View File

@ -688,10 +688,10 @@ function get_is_filter_suggestions(last: NarrowTerm, terms: NarrowTerm[]): Sugge
], ],
}, },
{ {
search_string: "is:alerted", search_string: "is:watched",
description_html: "messages with watched phrases", description_html: "messages with watched phrases",
is_people: false, is_people: false,
incompatible_patterns: [{operator: "is", operand: "alerted"}], incompatible_patterns: [{operator: "is", operand: "watched"}],
}, },
{ {
search_string: "is:unread", search_string: "is:unread",

View File

@ -30,7 +30,11 @@
{{~!-- squash whitespace --~}} {{~!-- squash whitespace --~}}
{{this.verb}}@-mentions {{this.verb}}@-mentions
{{~!-- squash whitespace --~}} {{~!-- squash whitespace --~}}
{{else if (or (eq this.operand "starred") (eq this.operand "alerted") (eq this.operand "unread"))}} {{else if (eq this.operand "watched")}}
{{~!-- squash whitespace --~}}
{{this.verb}}Messages with watched phrases
{{~!-- squash whitespace --~}}
{{else if (or (eq this.operand "starred") (eq this.operand "unread"))}}
{{~!-- squash whitespace --~}} {{~!-- squash whitespace --~}}
{{this.verb}}{{this.operand}} messages {{this.verb}}{{this.operand}} messages
{{~!-- squash whitespace --~}} {{~!-- squash whitespace --~}}

View File

@ -110,7 +110,7 @@
</td> </td>
</tr> </tr>
<tr> <tr>
<td class="operator">is:alerted</td> <td class="operator">is:watched</td>
<td class="definition"> <td class="definition">
{{t 'Narrow to messages with watched phrases.'}} {{t 'Narrow to messages with watched phrases.'}}
</td> </td>

View File

@ -44,62 +44,62 @@ const regular_message = {
const own_message = { const own_message = {
sender_email: "tester@zulip.com", sender_email: "tester@zulip.com",
content: "<p>hey this message alertone</p>", content: "<p>hey this message alertone</p>",
alerted: true, watched: true,
}; };
const other_message = { const other_message = {
sender_email: "another@zulip.com", sender_email: "another@zulip.com",
content: "<p>another alertone message</p>", content: "<p>another alertone message</p>",
alerted: true, watched: true,
}; };
const caps_message = { const caps_message = {
sender_email: "another@zulip.com", sender_email: "another@zulip.com",
content: "<p>another ALERTtwo message</p>", content: "<p>another ALERTtwo message</p>",
alerted: true, watched: true,
}; };
const alertwordboundary_message = { const alertwordboundary_message = {
sender_email: "another@zulip.com", sender_email: "another@zulip.com",
content: "<p>another alertthreemessage</p>", content: "<p>another alertthreemessage</p>",
alerted: false, watched: false,
}; };
const multialert_message = { const multialert_message = {
sender_email: "another@zulip.com", sender_email: "another@zulip.com",
content: "<p>another emoji alertone and then alerttwo</p>", content: "<p>another emoji alertone and then alerttwo</p>",
alerted: true, watched: true,
}; };
const unsafe_word_message = { const unsafe_word_message = {
sender_email: "another@zulip.com", sender_email: "another@zulip.com",
content: "<p>gotta al*rt.*s all</p>", content: "<p>gotta al*rt.*s all</p>",
alerted: true, watched: true,
}; };
const alert_in_url_message = { const alert_in_url_message = {
sender_email: "another@zulip.com", sender_email: "another@zulip.com",
content: "<p>http://www.google.com/alertone/me</p>", content: "<p>http://www.google.com/alertone/me</p>",
alerted: true, watched: true,
}; };
const question_word_message = { const question_word_message = {
sender_email: "another@zulip.com", sender_email: "another@zulip.com",
content: "<p>still alertone? me</p>", content: "<p>still alertone? me</p>",
alerted: true, watched: true,
}; };
const typo_word_message = { const typo_word_message = {
sender_email: "another@zulip.com", sender_email: "another@zulip.com",
content: "<p>alertones alerttwo alerttwo alertthreez</p>", content: "<p>alertones alerttwo alerttwo alertthreez</p>",
alerted: true, watched: true,
}; };
const alert_domain_message = { const alert_domain_message = {
sender_email: "another@zulip.com", sender_email: "another@zulip.com",
content: content:
'<p>now with link <a href="http://www.alerttwo.us/foo/bar" target="_blank" title="http://www.alerttwo.us/foo/bar">www.alerttwo.us/foo/bar</a></p>', '<p>now with link <a href="http://www.alerttwo.us/foo/bar" target="_blank" title="http://www.alerttwo.us/foo/bar">www.alerttwo.us/foo/bar</a></p>',
alerted: true, watched: true,
}; };
// This test ensure we are not mucking up rendered HTML content. // This test ensure we are not mucking up rendered HTML content.
const message_with_emoji = { const message_with_emoji = {
sender_email: "another@zulip.com", sender_email: "another@zulip.com",
content: content:
'<p>I <img alt=":heart:" class="emoji" src="/static/generated/emoji/images/emoji/unicode/2764.png" title="heart"> emoji!</p>', '<p>I <img alt=":heart:" class="emoji" src="/static/generated/emoji/images/emoji/unicode/2764.png" title="heart"> emoji!</p>',
alerted: true, watched: true,
}; };
run_test("notifications", () => { run_test("notifications", () => {
@ -188,7 +188,7 @@ run_test("munging", () => {
{ {
sender_email: "another@zulip.com", sender_email: "another@zulip.com",
content: `<p>FD&amp;C &lt;3 &gt;8 5'11" 5&#39;11&quot;</p>`, content: `<p>FD&amp;C &lt;3 &gt;8 5'11" 5&#39;11&quot;</p>`,
alerted: true, watched: true,
}, },
`<p><span class='alert-word'>FD&amp;C</span> <span class='alert-word'>&lt;3</span> <span class='alert-word'>&gt;8</span> <span class='alert-word'>5'11"</span> <span class='alert-word'>5&#39;11&quot;</span></p>`, `<p><span class='alert-word'>FD&amp;C</span> <span class='alert-word'>&lt;3</span> <span class='alert-word'>&gt;8</span> <span class='alert-word'>5'11"</span> <span class='alert-word'>5&#39;11&quot;</span></p>`,
); );

View File

@ -68,14 +68,14 @@ run_test("message_store", () => {
const in_message = {...messages.isaac_to_denmark_stream}; const in_message = {...messages.isaac_to_denmark_stream};
assert.equal(in_message.alerted, undefined); assert.equal(in_message.watched, undefined);
// Let's add a message into our message_store via // Let's add a message into our message_store via
// message_helper.process_new_message. // message_helper.process_new_message.
assert.equal(message_store.get(in_message.id), undefined); assert.equal(message_store.get(in_message.id), undefined);
message_helper.process_new_message(in_message); message_helper.process_new_message(in_message);
const message = message_store.get(in_message.id); const message = message_store.get(in_message.id);
assert.equal(message.alerted, true); assert.equal(message.watched, true);
// There are more side effects. // There are more side effects.
const topic_names = stream_topic_history.get_recent_topic_names(denmark_stream.stream_id); const topic_names = stream_topic_history.get_recent_topic_names(denmark_stream.stream_id);

View File

@ -537,11 +537,11 @@ function assert_not_mark_read_with_is_operands(additional_terms_to_test) {
filter = new Filter([...additional_terms_to_test, ...is_operator]); filter = new Filter([...additional_terms_to_test, ...is_operator]);
assert.ok(!filter.can_mark_messages_read()); assert.ok(!filter.can_mark_messages_read());
is_operator = [{operator: "is", operand: "alerted"}]; is_operator = [{operator: "is", operand: "watched"}];
filter = new Filter([...additional_terms_to_test, ...is_operator]); filter = new Filter([...additional_terms_to_test, ...is_operator]);
assert.ok(!filter.can_mark_messages_read()); assert.ok(!filter.can_mark_messages_read());
is_operator = [{operator: "is", operand: "alerted", negated: true}]; is_operator = [{operator: "is", operand: "watched", negated: true}];
filter = new Filter([...additional_terms_to_test, ...is_operator]); filter = new Filter([...additional_terms_to_test, ...is_operator]);
assert.ok(!filter.can_mark_messages_read()); assert.ok(!filter.can_mark_messages_read());
@ -970,9 +970,9 @@ test("predicate_basics", ({override}) => {
assert.ok(predicate({unread: true})); assert.ok(predicate({unread: true}));
assert.ok(!predicate({unread: false})); assert.ok(!predicate({unread: false}));
predicate = get_predicate([["is", "alerted"]]); predicate = get_predicate([["is", "watched"]]);
assert.ok(predicate({alerted: true})); assert.ok(predicate({watched: true}));
assert.ok(!predicate({alerted: false})); assert.ok(!predicate({watched: false}));
assert.ok(!predicate({})); assert.ok(!predicate({}));
predicate = get_predicate([["is", "mentioned"]]); predicate = get_predicate([["is", "mentioned"]]);
@ -1537,8 +1537,8 @@ test("describe", ({mock_template}) => {
string = "@-mentions"; string = "@-mentions";
assert.equal(Filter.search_description_as_html(narrow), string); assert.equal(Filter.search_description_as_html(narrow), string);
narrow = [{operator: "is", operand: "alerted"}]; narrow = [{operator: "is", operand: "watched"}];
string = "alerted messages"; string = "Messages with watched phrases";
assert.equal(Filter.search_description_as_html(narrow), string); assert.equal(Filter.search_description_as_html(narrow), string);
narrow = [{operator: "is", operand: "resolved"}]; narrow = [{operator: "is", operand: "resolved"}];
@ -1779,16 +1779,16 @@ test("term_type", () => {
}); });
test("first_valid_id_from", ({override}) => { test("first_valid_id_from", ({override}) => {
const terms = [{operator: "is", operand: "alerted"}]; const terms = [{operator: "is", operand: "watched"}];
const filter = new Filter(terms); const filter = new Filter(terms);
const messages = { const messages = {
5: {id: 5, alerted: true}, 5: {id: 5, watched: true},
10: {id: 10}, 10: {id: 10},
20: {id: 20, alerted: true}, 20: {id: 20, watched: true},
30: {id: 30, type: stream_message}, 30: {id: 30, type: stream_message},
40: {id: 40, alerted: false}, 40: {id: 40, watched: false},
}; };
const msg_ids = [10, 20, 30, 40]; const msg_ids = [10, 20, 30, 40];
@ -2130,7 +2130,7 @@ test("navbar_helpers", ({override}) => {
{operator: "dm", operand: "joe@example.com,STEVE@foo.com,sally@doesnotexist.com"}, {operator: "dm", operand: "joe@example.com,STEVE@foo.com,sally@doesnotexist.com"},
]; ];
// not common narrows, but used for browser title updates // not common narrows, but used for browser title updates
const is_alerted = [{operator: "is", operand: "alerted"}]; const is_watched = [{operator: "is", operand: "watched"}];
const is_unread = [{operator: "is", operand: "unread"}]; const is_unread = [{operator: "is", operand: "unread"}];
const channel_topic_near = [ const channel_topic_near = [
{operator: "channel", operand: foo_stream_id.toString()}, {operator: "channel", operand: foo_stream_id.toString()},
@ -2317,10 +2317,10 @@ test("navbar_helpers", ({override}) => {
link: "/help/emoji-reactions", link: "/help/emoji-reactions",
}, },
{ {
terms: is_alerted, terms: is_watched,
is_common_narrow: false, is_common_narrow: false,
icon: undefined, icon: undefined,
title: "translated: Alerted messages", title: "translated: Messages with watched phrases",
redirect_url_with_search: "#", redirect_url_with_search: "#",
}, },
{ {

View File

@ -134,7 +134,7 @@ run_test("update_messages", ({override}) => {
assert.deepEqual(rendered_mgs, [ assert.deepEqual(rendered_mgs, [
{ {
display_reply_to: undefined, display_reply_to: undefined,
alerted: false, watched: false,
clean_reactions: new Map(), clean_reactions: new Map(),
collapsed: false, collapsed: false,
content: "<b>new content</b>", content: "<b>new content</b>",

View File

@ -118,7 +118,7 @@ test("process_new_message", () => {
assert.equal(message.reply_to, "bob@example.com,cindy@example.com"); assert.equal(message.reply_to, "bob@example.com,cindy@example.com");
assert.equal(message.to_user_ids, "103,104"); assert.equal(message.to_user_ids, "103,104");
assert.equal(message.display_reply_to, "Bob, Cindy"); assert.equal(message.display_reply_to, "Bob, Cindy");
assert.equal(message.alerted, true); assert.equal(message.watched, true);
assert.equal(message.is_me_message, false); assert.equal(message.is_me_message, false);
const retrieved_message = message_store.get(2067); const retrieved_message = message_store.get(2067);
@ -151,7 +151,7 @@ test("process_new_message", () => {
message = message_helper.process_new_message(message); message = message_helper.process_new_message(message);
assert.equal(message.reply_to, "denise@example.com"); assert.equal(message.reply_to, "denise@example.com");
assert.deepEqual(message.flags, undefined); assert.deepEqual(message.flags, undefined);
assert.equal(message.alerted, false); assert.equal(message.watched, false);
assert.deepEqual(message_user_ids.user_ids().sort(), [ assert.deepEqual(message_user_ids.user_ids().sort(), [
me.user_id, me.user_id,
@ -187,7 +187,7 @@ test("message_booleans_parity", () => {
mentioned_me_directly: false, mentioned_me_directly: false,
stream_wildcard_mentioned: true, stream_wildcard_mentioned: true,
topic_wildcard_mentioned: false, topic_wildcard_mentioned: false,
alerted: false, watched: false,
}); });
assert_bool_match(["topic_wildcard_mentioned"], { assert_bool_match(["topic_wildcard_mentioned"], {
@ -195,7 +195,7 @@ test("message_booleans_parity", () => {
mentioned_me_directly: false, mentioned_me_directly: false,
stream_wildcard_mentioned: false, stream_wildcard_mentioned: false,
topic_wildcard_mentioned: true, topic_wildcard_mentioned: true,
alerted: false, watched: false,
}); });
assert_bool_match(["mentioned"], { assert_bool_match(["mentioned"], {
@ -203,7 +203,7 @@ test("message_booleans_parity", () => {
mentioned_me_directly: true, mentioned_me_directly: true,
stream_wildcard_mentioned: false, stream_wildcard_mentioned: false,
topic_wildcard_mentioned: false, topic_wildcard_mentioned: false,
alerted: false, watched: false,
}); });
assert_bool_match(["has_alert_word"], { assert_bool_match(["has_alert_word"], {
@ -211,7 +211,7 @@ test("message_booleans_parity", () => {
mentioned_me_directly: false, mentioned_me_directly: false,
stream_wildcard_mentioned: false, stream_wildcard_mentioned: false,
topic_wildcard_mentioned: false, topic_wildcard_mentioned: false,
alerted: true, watched: true,
}); });
}); });
@ -269,7 +269,7 @@ test("update_booleans", () => {
message.mentioned_me_directly = false; message.mentioned_me_directly = false;
message.stream_wildcard_mentioned = false; message.stream_wildcard_mentioned = false;
message.topic_wildcard_mentioned = false; message.topic_wildcard_mentioned = false;
message.alerted = false; message.watched = false;
let flags = ["mentioned", "has_alert_word", "read"]; let flags = ["mentioned", "has_alert_word", "read"];
message_store.update_booleans(message, flags); message_store.update_booleans(message, flags);
@ -277,7 +277,7 @@ test("update_booleans", () => {
assert.equal(message.mentioned_me_directly, true); assert.equal(message.mentioned_me_directly, true);
assert.equal(message.stream_wildcard_mentioned, false); assert.equal(message.stream_wildcard_mentioned, false);
assert.equal(message.topic_wildcard_mentioned, false); assert.equal(message.topic_wildcard_mentioned, false);
assert.equal(message.alerted, true); assert.equal(message.watched, true);
flags = ["stream_wildcard_mentioned", "unread"]; flags = ["stream_wildcard_mentioned", "unread"];
message_store.update_booleans(message, flags); message_store.update_booleans(message, flags);
@ -297,7 +297,7 @@ test("update_booleans", () => {
message_store.update_booleans(message, flags); message_store.update_booleans(message, flags);
assert.equal(message.mentioned, false); assert.equal(message.mentioned, false);
assert.equal(message.mentioned_me_directly, false); assert.equal(message.mentioned_me_directly, false);
assert.equal(message.alerted, false); assert.equal(message.watched, false);
assert.equal(message.stream_wildcard_mentioned, false); assert.equal(message.stream_wildcard_mentioned, false);
assert.equal(message.topic_wildcard_mentioned, false); assert.equal(message.topic_wildcard_mentioned, false);

View File

@ -285,16 +285,16 @@ run_test("is:mentioned with no unreads and no matches", () => {
test_with(fixture); test_with(fixture);
}); });
run_test("is:alerted with no unreads and one match", () => { run_test("is:watched with no unreads and one match", () => {
const fixture = { const fixture = {
filter_terms: [{operator: "is", operand: "alerted"}], filter_terms: [{operator: "is", operand: "watched"}],
unread_info: { unread_info: {
flavor: "not_found", flavor: "not_found",
}, },
has_found_newest: true, has_found_newest: true,
all_messages: [ all_messages: [
{id: 55, topic: "whatever", alerted: true}, {id: 55, topic: "whatever", watched: true},
{id: 57, topic: "whatever", alerted: false}, {id: 57, topic: "whatever", watched: false},
], ],
expected_id_info: { expected_id_info: {
target_id: undefined, target_id: undefined,

View File

@ -164,7 +164,6 @@ test("dm_suggestions", ({override, mock_template}) => {
suggestions = get_suggestions(query); suggestions = get_suggestions(query);
expected = [ expected = [
"is:dm al", "is:dm al",
"is:dm is:alerted",
"is:dm dm:alice@zulip.com", "is:dm dm:alice@zulip.com",
"is:dm sender:alice@zulip.com", "is:dm sender:alice@zulip.com",
"is:dm dm-including:alice@zulip.com", "is:dm dm-including:alice@zulip.com",
@ -238,16 +237,15 @@ test("dm_suggestions", ({override, mock_template}) => {
assert.deepEqual(suggestions.strings, expected); assert.deepEqual(suggestions.strings, expected);
// Make sure suggestions still work if preceding tokens // Make sure suggestions still work if preceding tokens
query = "is:alerted sender:ted@zulip.com"; query = "is:watched sender:ted@zulip.com";
suggestions = get_suggestions(query); suggestions = get_suggestions(query);
expected = ["is:alerted sender:ted@zulip.com", "is:alerted"]; expected = ["is:watched sender:ted@zulip.com", "is:watched"];
assert.deepEqual(suggestions.strings, expected); assert.deepEqual(suggestions.strings, expected);
query = "is:starred has:link is:dm al"; query = "is:starred has:link is:dm al";
suggestions = get_suggestions(query); suggestions = get_suggestions(query);
expected = [ expected = [
"is:starred has:link is:dm al", "is:starred has:link is:dm al",
"is:starred has:link is:dm is:alerted",
"is:starred has:link is:dm dm:alice@zulip.com", "is:starred has:link is:dm dm:alice@zulip.com",
"is:starred has:link is:dm sender:alice@zulip.com", "is:starred has:link is:dm sender:alice@zulip.com",
"is:starred has:link is:dm dm-including:alice@zulip.com", "is:starred has:link is:dm dm-including:alice@zulip.com",
@ -374,7 +372,7 @@ test("empty_query_suggestions", () => {
"is:starred", "is:starred",
"is:mentioned", "is:mentioned",
"is:followed", "is:followed",
"is:alerted", "is:watched",
"is:unread", "is:unread",
"is:resolved", "is:resolved",
"sender:myself@zulip.com", "sender:myself@zulip.com",
@ -394,7 +392,7 @@ test("empty_query_suggestions", () => {
assert.equal(describe("is:dm"), "Direct messages"); assert.equal(describe("is:dm"), "Direct messages");
assert.equal(describe("is:starred"), "Starred messages"); assert.equal(describe("is:starred"), "Starred messages");
assert.equal(describe("is:mentioned"), "@-mentions"); assert.equal(describe("is:mentioned"), "@-mentions");
assert.equal(describe("is:alerted"), "Messages with watched phrases"); assert.equal(describe("is:watched"), "Messages with watched phrases");
assert.equal(describe("is:unread"), "Unread messages"); assert.equal(describe("is:unread"), "Unread messages");
assert.equal(describe("is:resolved"), "Topics marked as resolved"); assert.equal(describe("is:resolved"), "Topics marked as resolved");
assert.equal(describe("is:followed"), "Followed topics"); assert.equal(describe("is:followed"), "Followed topics");
@ -457,9 +455,9 @@ test("has_suggestions", ({override, mock_template}) => {
assert.deepEqual(suggestions.strings, expected); assert.deepEqual(suggestions.strings, expected);
// 66 is misc channel id. // 66 is misc channel id.
query = "channel:66 is:alerted has:lin"; query = "channel:66 is:watched has:lin";
suggestions = get_suggestions(query); suggestions = get_suggestions(query);
expected = ["channel:66 is:alerted has:link", "channel:66 is:alerted", "channel:66"]; expected = ["channel:66 is:watched has:link", "channel:66 is:watched", "channel:66"];
assert.deepEqual(suggestions.strings, expected); assert.deepEqual(suggestions.strings, expected);
}); });
@ -477,7 +475,7 @@ test("check_is_suggestions", ({override, mock_template}) => {
"is:starred", "is:starred",
"is:mentioned", "is:mentioned",
"is:followed", "is:followed",
"is:alerted", "is:watched",
"is:unread", "is:unread",
"is:resolved", "is:resolved",
"dm:alice@zulip.com", "dm:alice@zulip.com",
@ -494,7 +492,7 @@ test("check_is_suggestions", ({override, mock_template}) => {
assert.equal(describe("is:dm"), "Direct messages"); assert.equal(describe("is:dm"), "Direct messages");
assert.equal(describe("is:starred"), "Starred messages"); assert.equal(describe("is:starred"), "Starred messages");
assert.equal(describe("is:mentioned"), "@-mentions"); assert.equal(describe("is:mentioned"), "@-mentions");
assert.equal(describe("is:alerted"), "Messages with watched phrases"); assert.equal(describe("is:watched"), "Messages with watched phrases");
assert.equal(describe("is:unread"), "Unread messages"); assert.equal(describe("is:unread"), "Unread messages");
assert.equal(describe("is:resolved"), "Topics marked as resolved"); assert.equal(describe("is:resolved"), "Topics marked as resolved");
assert.equal(describe("is:followed"), "Followed topics"); assert.equal(describe("is:followed"), "Followed topics");
@ -507,7 +505,7 @@ test("check_is_suggestions", ({override, mock_template}) => {
"-is:starred", "-is:starred",
"-is:mentioned", "-is:mentioned",
"-is:followed", "-is:followed",
"-is:alerted", "-is:watched",
"-is:unread", "-is:unread",
"-is:resolved", "-is:resolved",
]; ];
@ -516,7 +514,7 @@ test("check_is_suggestions", ({override, mock_template}) => {
assert.equal(describe("-is:dm"), "Exclude direct messages"); assert.equal(describe("-is:dm"), "Exclude direct messages");
assert.equal(describe("-is:starred"), "Exclude starred messages"); assert.equal(describe("-is:starred"), "Exclude starred messages");
assert.equal(describe("-is:mentioned"), "Exclude @-mentions"); assert.equal(describe("-is:mentioned"), "Exclude @-mentions");
assert.equal(describe("-is:alerted"), "Exclude messages with watched phrases"); assert.equal(describe("-is:watched"), "Exclude messages with watched phrases");
assert.equal(describe("-is:unread"), "Exclude unread messages"); assert.equal(describe("-is:unread"), "Exclude unread messages");
assert.equal(describe("-is:resolved"), "Exclude topics marked as resolved"); assert.equal(describe("-is:resolved"), "Exclude topics marked as resolved");
assert.equal(describe("-is:followed"), "Exclude followed topics"); assert.equal(describe("-is:followed"), "Exclude followed topics");
@ -530,7 +528,7 @@ test("check_is_suggestions", ({override, mock_template}) => {
"is:starred", "is:starred",
"is:mentioned", "is:mentioned",
"is:followed", "is:followed",
"is:alerted", "is:watched",
"is:unread", "is:unread",
"is:resolved", "is:resolved",
]; ];
@ -707,13 +705,13 @@ test("topic_suggestions", ({override, mock_template}) => {
]; ];
assert.deepEqual(suggestions.strings, expected); assert.deepEqual(suggestions.strings, expected);
suggestions = get_suggestions(`is:alerted channel:${devel_id} is:starred topic:`); suggestions = get_suggestions(`is:watched channel:${devel_id} is:starred topic:`);
expected = [ expected = [
`is:alerted channel:${devel_id} is:starred topic:`, `is:watched channel:${devel_id} is:starred topic:`,
`is:alerted channel:${devel_id} is:starred topic:REXX`, `is:watched channel:${devel_id} is:starred topic:REXX`,
`is:alerted channel:${devel_id} is:starred`, `is:watched channel:${devel_id} is:starred`,
`is:alerted channel:${devel_id}`, `is:watched channel:${devel_id}`,
"is:alerted", "is:watched",
]; ];
assert.deepEqual(suggestions.strings, expected); assert.deepEqual(suggestions.strings, expected);
@ -1008,13 +1006,13 @@ test("operator_suggestions", ({override, mock_template}) => {
assert.deepEqual(suggestions.strings, expected); assert.deepEqual(suggestions.strings, expected);
// 66 is a misc channel id. // 66 is a misc channel id.
query = "channel:66 is:alerted -f"; query = "channel:66 is:watched -f";
suggestions = get_suggestions(query); suggestions = get_suggestions(query);
expected = [ expected = [
"channel:66 is:alerted -f", "channel:66 is:watched -f",
"channel:66 is:alerted -sender:myself@zulip.com", "channel:66 is:watched -sender:myself@zulip.com",
"channel:66 is:alerted -sender:", "channel:66 is:watched -sender:",
"channel:66 is:alerted", "channel:66 is:watched",
"channel:66", "channel:66",
]; ];
assert.deepEqual(suggestions.strings, expected); assert.deepEqual(suggestions.strings, expected);

View File

@ -403,7 +403,7 @@ class NarrowBuilder:
) )
cond = column("flags", Integer).op("&")(mention_flags_mask) != 0 cond = column("flags", Integer).op("&")(mention_flags_mask) != 0
return query.where(maybe_negate(cond)) return query.where(maybe_negate(cond))
elif operand == "alerted": elif operand in ["alerted", "watched"]:
cond = column("flags", Integer).op("&")(UserMessage.flags.has_alert_word.mask) != 0 cond = column("flags", Integer).op("&")(UserMessage.flags.has_alert_word.mask) != 0
return query.where(maybe_negate(cond)) return query.where(maybe_negate(cond))
elif operand == "resolved": elif operand == "resolved":

View File

@ -63,7 +63,7 @@ def build_narrow_predicate(
elif operator == "is" and operand == "unread": elif operator == "is" and operand == "unread":
if "read" in flags: if "read" in flags:
return False return False
elif operator == "is" and operand in ["alerted", "mentioned"]: elif operator == "is" and operand in ["alerted", "mentioned", "watched"]:
if "mentioned" not in flags: if "mentioned" not in flags:
return False return False
elif operator == "is" and operand == "resolved": elif operator == "is" and operand == "resolved":

View File

@ -228,7 +228,7 @@ class NarrowBuilderTest(ZulipTestCase):
self._do_add_term_test(term, "WHERE (flags & %(flags_1)s) = %(param_1)s") self._do_add_term_test(term, "WHERE (flags & %(flags_1)s) = %(param_1)s")
def test_add_term_using_is_operator_and_non_dm_operand(self) -> None: def test_add_term_using_is_operator_and_non_dm_operand(self) -> None:
for operand in ["starred", "mentioned", "alerted"]: for operand in ["starred", "mentioned", "alerted", "watched"]:
term = NarrowParameter(operator="is", operand=operand) term = NarrowParameter(operator="is", operand=operand)
self._do_add_term_test(term, "WHERE (flags & %(flags_1)s) != %(param_1)s") self._do_add_term_test(term, "WHERE (flags & %(flags_1)s) != %(param_1)s")
@ -257,6 +257,16 @@ class NarrowBuilderTest(ZulipTestCase):
) )
self._do_add_term_test(term, where_clause, params) self._do_add_term_test(term, where_clause, params)
self._do_add_term_test(term, where_clause, params)
term = NarrowParameter(operator="is", operand="watched", negated=True)
where_clause = "WHERE (flags & %(flags_1)s) = %(param_1)s"
params = dict(
flags_1=UserMessage.flags.has_alert_word.mask,
param_1=0,
)
self._do_add_term_test(term, where_clause, params)
term = NarrowParameter(operator="is", operand="mentioned", negated=True) term = NarrowParameter(operator="is", operand="mentioned", negated=True)
where_clause = "WHERE (flags & %(flags_1)s) = %(param_1)s" where_clause = "WHERE (flags & %(flags_1)s) = %(param_1)s"
mention_flags_mask = ( mention_flags_mask = (
@ -897,6 +907,13 @@ class NarrowLibraryTest(ZulipTestCase):
) )
) )
self.assertFalse(
narrow_predicate(
message={},
flags=["watched"],
)
)
### ###
narrow_predicate = build_narrow_predicate([NarrowTerm(operator="is", operand="alerted")]) narrow_predicate = build_narrow_predicate([NarrowTerm(operator="is", operand="alerted")])
@ -917,6 +934,24 @@ class NarrowLibraryTest(ZulipTestCase):
### ###
narrow_predicate = build_narrow_predicate([NarrowTerm(operator="is", operand="watched")])
self.assertTrue(
narrow_predicate(
message={},
flags=["mentioned"],
)
)
self.assertFalse(
narrow_predicate(
message={},
flags=["starred"],
)
)
###
narrow_predicate = build_narrow_predicate([NarrowTerm(operator="is", operand="mentioned")]) narrow_predicate = build_narrow_predicate([NarrowTerm(operator="is", operand="mentioned")])
self.assertTrue( self.assertTrue(
@ -1155,6 +1190,11 @@ class IncludeHistoryTest(ZulipTestCase):
NarrowParameter(operator="is", operand="alerted"), NarrowParameter(operator="is", operand="alerted"),
] ]
self.assertFalse(ok_to_include_history(narrow, user_profile, False)) self.assertFalse(ok_to_include_history(narrow, user_profile, False))
narrow = [
NarrowParameter(operator="channels", operand="public"),
NarrowParameter(operator="is", operand="watched"),
]
self.assertFalse(ok_to_include_history(narrow, user_profile, False))
narrow = [ narrow = [
NarrowParameter(operator="channels", operand="public"), NarrowParameter(operator="channels", operand="public"),
NarrowParameter(operator="is", operand="resolved"), NarrowParameter(operator="is", operand="resolved"),