mirror of https://github.com/zulip/zulip.git
filter: Use "channels" operator for the Filter class.
Update the Filter class to use "channels" as the canoncial operator for public stream searches and web-public message fetch narrows, but keep using "streams" for user-facing text and URLs. When searching, "channels" does not create any suggestions until a colon is added and then it shows suggestions with "streams". And when a search string with channel as an operator is entered, then it is replaced by "streams" as well. Part of stream to channel rename project.
This commit is contained in:
parent
1e7c5b38f8
commit
a446033f32
|
@ -56,10 +56,11 @@ type Part =
|
|||
operand: string;
|
||||
};
|
||||
|
||||
// TODO: When "stream" is renamed to "channel", this placeholder
|
||||
// TODO: When "stream" is renamed to "channel", these placeholders
|
||||
// should be removed, or replaced with helper functions similar
|
||||
// to util.is_topic_synonym.
|
||||
const CHANNEL_SYNONYM = "stream";
|
||||
const CHANNELS_SYNONYM = "streams";
|
||||
|
||||
function zephyr_stream_name_match(message: Message & {type: "stream"}, operand: string): boolean {
|
||||
// Zephyr users expect narrowing to "social" to also show messages to /^(un)*social(.d)*$/
|
||||
|
@ -278,6 +279,10 @@ export class Filter {
|
|||
if (operator === CHANNEL_SYNONYM) {
|
||||
return "channel";
|
||||
}
|
||||
|
||||
if (operator === CHANNELS_SYNONYM) {
|
||||
return "channels";
|
||||
}
|
||||
return operator;
|
||||
}
|
||||
|
||||
|
@ -454,7 +459,7 @@ export class Filter {
|
|||
if (term.operator === "") {
|
||||
return term.operand;
|
||||
}
|
||||
const operator = util.canonicalize_stream_synonym(term.operator);
|
||||
const operator = util.canonicalize_stream_synonyms(term.operator);
|
||||
return sign + operator + ":" + Filter.encodeOperand(term.operand.toString());
|
||||
});
|
||||
return term_strings.join(" ");
|
||||
|
@ -469,7 +474,7 @@ export class Filter {
|
|||
|
||||
result += operator;
|
||||
|
||||
if (["is", "has", "in", "streams"].includes(operator)) {
|
||||
if (["is", "has", "in", "channels"].includes(operator)) {
|
||||
result += "-" + operand;
|
||||
}
|
||||
|
||||
|
@ -479,7 +484,7 @@ export class Filter {
|
|||
static sorted_term_types(term_types: string[]): string[] {
|
||||
const levels = [
|
||||
"in",
|
||||
"streams-public",
|
||||
"channels-public",
|
||||
"channel",
|
||||
"topic",
|
||||
"dm",
|
||||
|
@ -530,8 +535,8 @@ export class Filter {
|
|||
switch (operator) {
|
||||
case "channel":
|
||||
return verb + CHANNEL_SYNONYM;
|
||||
case "streams":
|
||||
return verb + "streams";
|
||||
case "channels":
|
||||
return verb + CHANNELS_SYNONYM;
|
||||
case "near":
|
||||
return verb + "messages around";
|
||||
|
||||
|
@ -743,10 +748,10 @@ export class Filter {
|
|||
"not-is-resolved",
|
||||
"in-home",
|
||||
"in-all",
|
||||
"streams-public",
|
||||
"not-streams-public",
|
||||
"streams-web-public",
|
||||
"not-streams-web-public",
|
||||
"channels-public",
|
||||
"not-channels-public",
|
||||
"channels-web-public",
|
||||
"not-channels-web-public",
|
||||
"near",
|
||||
]);
|
||||
|
||||
|
@ -835,7 +840,7 @@ export class Filter {
|
|||
if (_.isEqual(term_types, ["is-starred"])) {
|
||||
return true;
|
||||
}
|
||||
if (_.isEqual(term_types, ["streams-public"])) {
|
||||
if (_.isEqual(term_types, ["channels-public"])) {
|
||||
return true;
|
||||
}
|
||||
if (_.isEqual(term_types, ["sender"])) {
|
||||
|
@ -894,8 +899,8 @@ export class Filter {
|
|||
return "/#narrow/is/starred";
|
||||
case "is-mentioned":
|
||||
return "/#narrow/is/mentioned";
|
||||
case "streams-public":
|
||||
return "/#narrow/streams/public";
|
||||
case "channels-public":
|
||||
return "/#narrow/" + CHANNELS_SYNONYM + "/public";
|
||||
case "dm":
|
||||
return "/#narrow/dm/" + people.emails_to_slug(this.operands("dm").join(","));
|
||||
case "is-resolved":
|
||||
|
@ -1021,7 +1026,7 @@ export class Filter {
|
|||
return $t({defaultMessage: "All messages"});
|
||||
case "in-all":
|
||||
return $t({defaultMessage: "All messages including muted streams"});
|
||||
case "streams-public":
|
||||
case "channels-public":
|
||||
return $t({defaultMessage: "Messages in all public streams"});
|
||||
case "is-starred":
|
||||
return $t({defaultMessage: "Starred messages"});
|
||||
|
@ -1057,14 +1062,14 @@ export class Filter {
|
|||
}
|
||||
|
||||
includes_full_stream_history(): boolean {
|
||||
return this.has_operator("channel") || this.has_operator("streams");
|
||||
return this.has_operator("channel") || this.has_operator("channels");
|
||||
}
|
||||
|
||||
is_personal_filter(): boolean {
|
||||
// Whether the filter filters for user-specific data in the
|
||||
// UserMessage table, such as stars or mentions.
|
||||
//
|
||||
// Such filters should not advertise "streams:public" as it
|
||||
// Such filters should not advertise "channels:public" as it
|
||||
// will never add additional results.
|
||||
return this.has_operand("is", "mentioned") || this.has_operand("is", "starred");
|
||||
}
|
||||
|
@ -1089,9 +1094,9 @@ export class Filter {
|
|||
return false;
|
||||
}
|
||||
|
||||
// TODO: It's not clear why `streams:` filters would not be
|
||||
// TODO: It's not clear why `channels:` filters would not be
|
||||
// applicable locally.
|
||||
if (this.has_operator("streams") || this.has_negated_operand("streams", "public")) {
|
||||
if (this.has_operator("channels") || this.has_negated_operand("channels", "public")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -92,6 +92,7 @@ export function is_create_new_stream_narrow(): boolean {
|
|||
}
|
||||
|
||||
export const allowed_web_public_narrows = [
|
||||
"channels",
|
||||
"channel",
|
||||
"streams",
|
||||
"stream",
|
||||
|
|
|
@ -94,7 +94,7 @@ export function search_terms_to_hash(terms?: NarrowTerm[]): string {
|
|||
|
||||
for (const term of terms) {
|
||||
// Support legacy tuples.
|
||||
const operator = util.canonicalize_stream_synonym(term.operator);
|
||||
const operator = util.canonicalize_stream_synonyms(term.operator);
|
||||
const operand = term.operand;
|
||||
|
||||
const sign = term.negated ? "-" : "";
|
||||
|
|
|
@ -301,7 +301,7 @@ export function load_messages(opts, attempt = 1) {
|
|||
// This is a bit of a hack; ideally we'd unify this logic in
|
||||
// some way with the above logic, and not need to do JSON
|
||||
// parsing/stringifying here.
|
||||
const web_public_narrow = {negated: false, operator: "streams", operand: "web-public"};
|
||||
const web_public_narrow = {negated: false, operator: "channels", operand: "web-public"};
|
||||
|
||||
if (!data.narrow) {
|
||||
/* For the "All messages" feed, this will be the only operator. */
|
||||
|
|
|
@ -1362,7 +1362,7 @@ export function get_mention_syntax(full_name: string, user_id?: number, silent =
|
|||
}
|
||||
const wildcard_match = full_name_matches_wildcard_mention(full_name);
|
||||
if (wildcard_match && user_id === undefined) {
|
||||
mention += util.canonicalize_stream_synonym(full_name);
|
||||
mention += util.canonicalize_stream_synonyms(full_name);
|
||||
} else {
|
||||
mention += full_name;
|
||||
}
|
||||
|
|
|
@ -123,7 +123,7 @@ function get_stream_suggestions(last: NarrowTerm, terms: NarrowTerm[]): Suggesti
|
|||
const valid = ["channel", "search", ""];
|
||||
const incompatible_patterns = [
|
||||
{operator: "channel"},
|
||||
{operator: "streams"},
|
||||
{operator: "channels"},
|
||||
{operator: "is", operand: "dm"},
|
||||
{operator: "dm"},
|
||||
{operator: "dm-including"},
|
||||
|
@ -557,7 +557,7 @@ function get_streams_filter_suggestions(last: NarrowTerm, terms: NarrowTerm[]):
|
|||
{operator: "dm-including"},
|
||||
{operator: "dm"},
|
||||
{operator: "in"},
|
||||
{operator: "streams"},
|
||||
{operator: "channels"},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
|
|
@ -281,10 +281,20 @@ export function is_stream_synonym(text: string): boolean {
|
|||
return text === "channel";
|
||||
}
|
||||
|
||||
export function canonicalize_stream_synonym(text: string): string {
|
||||
export function is_streams_synonym(text: string): boolean {
|
||||
return text === "channels";
|
||||
}
|
||||
|
||||
// For parts of the codebase that have been converted to use
|
||||
// channel/channels internally, this is used to convert those
|
||||
// back into stream/streams for external presentation.
|
||||
export function canonicalize_stream_synonyms(text: string): string {
|
||||
if (is_stream_synonym(text.toLowerCase())) {
|
||||
return "stream";
|
||||
}
|
||||
if (is_streams_synonym(text.toLowerCase())) {
|
||||
return "streams";
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
|
|
|
@ -214,10 +214,10 @@ test("basics", () => {
|
|||
terms = [{operator: "streams", operand: "public", negated: true}];
|
||||
filter = new Filter(terms);
|
||||
assert.ok(!filter.contains_only_private_messages());
|
||||
assert.ok(!filter.has_operator("streams"));
|
||||
assert.ok(!filter.has_operator("channels"));
|
||||
assert.ok(!filter.can_mark_messages_read());
|
||||
assert.ok(filter.supports_collapsing_recipients());
|
||||
assert.ok(filter.has_negated_operand("streams", "public"));
|
||||
assert.ok(filter.has_negated_operand("channels", "public"));
|
||||
assert.ok(!filter.can_apply_locally());
|
||||
assert.ok(!filter.is_personal_filter());
|
||||
assert.ok(!filter.is_conversation_view());
|
||||
|
@ -225,10 +225,22 @@ test("basics", () => {
|
|||
terms = [{operator: "streams", operand: "public"}];
|
||||
filter = new Filter(terms);
|
||||
assert.ok(!filter.contains_only_private_messages());
|
||||
assert.ok(filter.has_operator("streams"));
|
||||
assert.ok(filter.has_operator("channels"));
|
||||
assert.ok(!filter.can_mark_messages_read());
|
||||
assert.ok(filter.supports_collapsing_recipients());
|
||||
assert.ok(!filter.has_negated_operand("streams", "public"));
|
||||
assert.ok(!filter.has_negated_operand("channels", "public"));
|
||||
assert.ok(!filter.can_apply_locally());
|
||||
assert.ok(filter.includes_full_stream_history());
|
||||
assert.ok(!filter.is_personal_filter());
|
||||
assert.ok(!filter.is_conversation_view());
|
||||
|
||||
terms = [{operator: "channels", operand: "public"}];
|
||||
filter = new Filter(terms);
|
||||
assert.ok(!filter.contains_only_private_messages());
|
||||
assert.ok(filter.has_operator("channels"));
|
||||
assert.ok(!filter.can_mark_messages_read());
|
||||
assert.ok(filter.supports_collapsing_recipients());
|
||||
assert.ok(!filter.has_negated_operand("channels", "public"));
|
||||
assert.ok(!filter.can_apply_locally());
|
||||
assert.ok(filter.includes_full_stream_history());
|
||||
assert.ok(!filter.is_personal_filter());
|
||||
|
@ -1442,7 +1454,7 @@ test("term_type", () => {
|
|||
};
|
||||
}
|
||||
|
||||
assert_term_type(term("streams", "public"), "streams-public");
|
||||
assert_term_type(term("channels", "public"), "channels-public");
|
||||
assert_term_type(term("channel", "whatever"), "channel");
|
||||
assert_term_type(term("dm", "whomever"), "dm");
|
||||
assert_term_type(term("dm", "whomever", true), "not-dm");
|
||||
|
@ -1466,7 +1478,7 @@ test("term_type", () => {
|
|||
assert_term_sort(["bogus", "channel", "topic"], ["channel", "topic", "bogus"]);
|
||||
assert_term_sort(["channel", "topic", "channel"], ["channel", "channel", "topic"]);
|
||||
|
||||
assert_term_sort(["search", "streams-public"], ["streams-public", "search"]);
|
||||
assert_term_sort(["search", "channels-public"], ["channels-public", "search"]);
|
||||
|
||||
const terms = [
|
||||
{operator: "topic", operand: "lunch"},
|
||||
|
|
|
@ -33,6 +33,7 @@ const hash_util = zrequire("hash_util");
|
|||
const hashchange = zrequire("hashchange");
|
||||
const narrow = zrequire("../src/narrow");
|
||||
const stream_data = zrequire("stream_data");
|
||||
const {Filter} = zrequire("../src/filter");
|
||||
|
||||
run_test("terms_round_trip", () => {
|
||||
let terms;
|
||||
|
@ -78,6 +79,29 @@ run_test("terms_round_trip", () => {
|
|||
assert.deepEqual(narrow, [{operator: "stream", operand: "Florida, USA", negated: false}]);
|
||||
});
|
||||
|
||||
run_test("stream_to_channel_rename", () => {
|
||||
let terms;
|
||||
let hash;
|
||||
let narrow;
|
||||
let filter;
|
||||
|
||||
terms = [{operator: "channel", operand: "devel"}];
|
||||
hash = hash_util.search_terms_to_hash(terms);
|
||||
assert.equal(hash, "#narrow/stream/devel");
|
||||
narrow = hash_util.parse_narrow(hash.split("/"));
|
||||
assert.deepEqual(narrow, [{operator: "stream", operand: "devel", negated: false}]);
|
||||
filter = new Filter(narrow);
|
||||
assert.deepEqual(filter.terms(), [{operator: "channel", operand: "devel", negated: false}]);
|
||||
|
||||
terms = [{operator: "channels", operand: "public"}];
|
||||
hash = hash_util.search_terms_to_hash(terms);
|
||||
assert.equal(hash, "#narrow/streams/public");
|
||||
narrow = hash_util.parse_narrow(hash.split("/"));
|
||||
assert.deepEqual(narrow, [{operator: "streams", operand: "public", negated: false}]);
|
||||
filter = new Filter(narrow);
|
||||
assert.deepEqual(filter.terms(), [{operator: "channels", operand: "public", negated: false}]);
|
||||
});
|
||||
|
||||
run_test("terms_trailing_slash", () => {
|
||||
const hash = "#narrow/stream/devel/topic/algol/";
|
||||
const narrow = hash_util.parse_narrow(hash.split("/"));
|
||||
|
|
Loading…
Reference in New Issue