mirror of https://github.com/zulip/zulip.git
filter: Use stream id instead of stream name.
This commit is contained in:
parent
2be181c367
commit
dba1af84e0
|
@ -186,16 +186,16 @@ export function initialize() {
|
|||
|
||||
// Renarrow to the unresolved topic if currently viewing the resolved topic.
|
||||
const current_filter = narrow_state.filter();
|
||||
const channel_name = sub_store.maybe_get_stream_name(stream_id);
|
||||
const stream_id_string = stream_id.toString();
|
||||
if (
|
||||
current_filter &&
|
||||
(current_filter.is_conversation_view() ||
|
||||
current_filter.is_conversation_view_with_near()) &&
|
||||
current_filter.has_topic(channel_name, topic_name)
|
||||
current_filter.has_topic(stream_id_string, topic_name)
|
||||
) {
|
||||
message_view.show(
|
||||
[
|
||||
{operator: "channel", operand: channel_name},
|
||||
{operator: "channel", operand: stream_id_string},
|
||||
{operator: "topic", operand: new_topic},
|
||||
],
|
||||
{},
|
||||
|
|
|
@ -9,6 +9,7 @@ import * as compose_ui from "./compose_ui";
|
|||
import * as hash_util from "./hash_util";
|
||||
import * as message_lists from "./message_lists";
|
||||
import * as rows from "./rows";
|
||||
import * as stream_data from "./stream_data";
|
||||
import * as topic_link_util from "./topic_link_util";
|
||||
import * as util from "./util";
|
||||
|
||||
|
@ -662,7 +663,10 @@ export function try_stream_topic_syntax_text(text: string): string | null {
|
|||
return null;
|
||||
}
|
||||
|
||||
if (topic_link_util.will_produce_broken_stream_topic_link(stream_topic.stream_name)) {
|
||||
const stream = stream_data.get_sub_by_id(stream_topic.stream_id);
|
||||
assert(stream !== undefined);
|
||||
const stream_name = stream.name;
|
||||
if (topic_link_util.will_produce_broken_stream_topic_link(stream_name)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -673,7 +677,7 @@ export function try_stream_topic_syntax_text(text: string): string | null {
|
|||
return null;
|
||||
}
|
||||
|
||||
let syntax_text = "#**" + stream_topic.stream_name;
|
||||
let syntax_text = "#**" + stream_name;
|
||||
if (stream_topic.topic_name) {
|
||||
syntax_text += ">" + stream_topic.topic_name;
|
||||
}
|
||||
|
|
|
@ -12,7 +12,6 @@ import * as messages_overlay_ui from "./messages_overlay_ui";
|
|||
import * as overlays from "./overlays";
|
||||
import * as people from "./people";
|
||||
import * as rendered_markdown from "./rendered_markdown";
|
||||
import * as stream_data from "./stream_data";
|
||||
import * as user_card_popover from "./user_card_popover";
|
||||
import * as user_group_popover from "./user_group_popover";
|
||||
|
||||
|
@ -30,7 +29,7 @@ function restore_draft(draft_id) {
|
|||
[
|
||||
{
|
||||
operator: "channel",
|
||||
operand: stream_data.get_stream_name_from_id(compose_args.stream_id),
|
||||
operand: compose_args.stream_id.toString(),
|
||||
},
|
||||
{operator: "topic", operand: compose_args.topic},
|
||||
],
|
||||
|
|
|
@ -18,7 +18,6 @@ import type {UserPillItem} from "./search_suggestion";
|
|||
import {current_user, realm} from "./state_data";
|
||||
import type {NarrowTerm} from "./state_data";
|
||||
import * as stream_data from "./stream_data";
|
||||
import type {StreamSubscription} from "./sub_store";
|
||||
import * as unread from "./unread";
|
||||
import * as user_topics from "./user_topics";
|
||||
import * as util from "./util";
|
||||
|
@ -75,12 +74,15 @@ type ValidOrInvalidUser =
|
|||
const CHANNEL_SYNONYM = "stream";
|
||||
const CHANNELS_SYNONYM = "streams";
|
||||
|
||||
function zephyr_stream_name_match(message: Message & {type: "stream"}, operand: string): boolean {
|
||||
function zephyr_stream_name_match(
|
||||
message: Message & {type: "stream"},
|
||||
stream_name: string,
|
||||
): boolean {
|
||||
// Zephyr users expect narrowing to "social" to also show messages to /^(un)*social(.d)*$/
|
||||
// (unsocial, ununsocial, social.d, etc)
|
||||
// TODO: hoist the regex compiling out of the closure
|
||||
const m = /^(?:un)*(.+?)(?:\.d)*$/i.exec(operand);
|
||||
let base_stream_name = operand;
|
||||
const m = /^(?:un)*(.+?)(?:\.d)*$/i.exec(stream_name);
|
||||
let base_stream_name = stream_name;
|
||||
if (m?.[1] !== undefined) {
|
||||
base_stream_name = m[1];
|
||||
}
|
||||
|
@ -88,8 +90,8 @@ function zephyr_stream_name_match(message: Message & {type: "stream"}, operand:
|
|||
/^(un)*/.source + _.escapeRegExp(base_stream_name) + /(\.d)*$/.source,
|
||||
"i",
|
||||
);
|
||||
const stream_name = stream_data.get_stream_name_from_id(message.stream_id);
|
||||
return related_regexp.test(stream_name);
|
||||
const message_stream_name = stream_data.get_stream_name_from_id(message.stream_id);
|
||||
return related_regexp.test(message_stream_name);
|
||||
}
|
||||
|
||||
function zephyr_topic_name_match(message: Message & {type: "stream"}, operand: string): boolean {
|
||||
|
@ -209,15 +211,12 @@ function message_matches_search_term(message: Message, operator: string, operand
|
|||
return false;
|
||||
}
|
||||
|
||||
operand = operand.toLowerCase();
|
||||
if (realm.realm_is_zephyr_mirror_realm) {
|
||||
return zephyr_stream_name_match(message, operand);
|
||||
const stream = stream_data.get_sub_by_id_string(operand);
|
||||
return zephyr_stream_name_match(message, stream?.name ?? "");
|
||||
}
|
||||
|
||||
// Try to match by stream_id if have a valid sub for
|
||||
// the operand. If we can't find the id, we return false.
|
||||
const stream_id = stream_data.get_stream_id(operand);
|
||||
return stream_id !== undefined && message.stream_id === stream_id;
|
||||
return message.stream_id.toString() === operand;
|
||||
}
|
||||
|
||||
case "topic":
|
||||
|
@ -291,7 +290,6 @@ const USER_OPERATORS = new Set([
|
|||
|
||||
export class Filter {
|
||||
_terms: NarrowTerm[];
|
||||
_sub?: StreamSubscription | undefined;
|
||||
_sorted_term_types?: string[] = undefined;
|
||||
_predicate?: (message: Message) => boolean;
|
||||
_can_mark_messages_read?: boolean;
|
||||
|
@ -355,7 +353,6 @@ export class Filter {
|
|||
break;
|
||||
|
||||
case "channel":
|
||||
operand = stream_data.get_name(operand);
|
||||
break;
|
||||
case "topic":
|
||||
break;
|
||||
|
@ -495,6 +492,18 @@ export class Filter {
|
|||
}
|
||||
operand = Filter.decodeOperand(parts.join(":"), operator);
|
||||
|
||||
// Check for user-entered channel name. If the name is valid,
|
||||
// convert it to id.
|
||||
if (
|
||||
(operator === "stream" || operator === "channel") &&
|
||||
Number.isNaN(Number.parseInt(operand, 10))
|
||||
) {
|
||||
const sub = stream_data.get_sub(operand);
|
||||
if (sub) {
|
||||
operand = sub.stream_id.toString();
|
||||
}
|
||||
}
|
||||
|
||||
// We use Filter.operator_to_prefix() to check if the
|
||||
// operator is known. If it is not known, then we treat
|
||||
// it as a search for the given string (which may contain
|
||||
|
@ -545,7 +554,7 @@ export class Filter {
|
|||
return Number.isInteger(Number(term.operand));
|
||||
case "channel":
|
||||
case "stream":
|
||||
return stream_data.get_sub(term.operand) !== undefined;
|
||||
return stream_data.get_sub_by_id_string(term.operand) !== undefined;
|
||||
case "channels":
|
||||
case "streams":
|
||||
return term.operand === "public";
|
||||
|
@ -715,7 +724,7 @@ export class Filter {
|
|||
Filter.canonicalize_operator(term.operator) === expected && !term.negated;
|
||||
|
||||
if (is(terms[0], "channel") && is(terms[1], "topic")) {
|
||||
const channel = terms[0].operand;
|
||||
const channel = stream_data.get_valid_sub_by_id_string(terms[0].operand).name;
|
||||
const topic = terms[1].operand;
|
||||
parts.push({
|
||||
type: "channel_topic",
|
||||
|
@ -783,6 +792,18 @@ export class Filter {
|
|||
};
|
||||
}
|
||||
if (prefix_for_operator !== "") {
|
||||
if (canonicalized_operator === "channel") {
|
||||
const stream = stream_data.get_sub_by_id_string(operand);
|
||||
if (stream) {
|
||||
return {
|
||||
type: "prefix_for_operator",
|
||||
prefix_for_operator,
|
||||
operand: stream.name,
|
||||
};
|
||||
}
|
||||
// Assume the operand is a partially formed name and return
|
||||
// the operator as the stream name in the next block.
|
||||
}
|
||||
return {
|
||||
type: "prefix_for_operator",
|
||||
prefix_for_operator,
|
||||
|
@ -863,12 +884,11 @@ export class Filter {
|
|||
const adjusted_term = {...term};
|
||||
if (
|
||||
Filter.canonicalize_operator(term.operator) === "channel" &&
|
||||
!util.lower_same(term.operand, message.display_recipient)
|
||||
term.operand !== message.stream_id.toString()
|
||||
) {
|
||||
adjusted_term.operand = message.display_recipient;
|
||||
adjusted_term.operand = message.stream_id.toString();
|
||||
terms_changed = true;
|
||||
}
|
||||
|
||||
if (
|
||||
Filter.canonicalize_operator(term.operator) === "topic" &&
|
||||
!util.lower_same(term.operand, message.topic)
|
||||
|
@ -890,11 +910,6 @@ export class Filter {
|
|||
setup_filter(terms: NarrowTerm[]): void {
|
||||
this._terms = this.fix_terms(terms);
|
||||
this.cached_sorted_terms_for_comparison = undefined;
|
||||
if (this.has_operator("channel")) {
|
||||
this._sub = stream_data.get_sub_by_name(this.operands("channel")[0]!);
|
||||
} else {
|
||||
this._sub = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
equals(filter: Filter, excluded_operators?: string[]): boolean {
|
||||
|
@ -948,12 +963,15 @@ export class Filter {
|
|||
public_terms(): NarrowTerm[] {
|
||||
const safe_to_return = this._terms.filter(
|
||||
// Filter out the embedded narrow (if any).
|
||||
(term) =>
|
||||
!(
|
||||
page_params.narrow_stream !== undefined &&
|
||||
term.operator === "channel" &&
|
||||
term.operand.toLowerCase() === page_params.narrow_stream.toLowerCase()
|
||||
),
|
||||
(term) => {
|
||||
// TODO(stream_id): Ideally we have `page_params.narrow_stream_id`
|
||||
if (page_params.narrow_stream === undefined || term.operator !== "channel") {
|
||||
return true;
|
||||
}
|
||||
const narrow_stream = stream_data.get_sub_by_name(page_params.narrow_stream);
|
||||
assert(narrow_stream !== undefined);
|
||||
return Number.parseInt(term.operand, 10) === narrow_stream.stream_id;
|
||||
},
|
||||
);
|
||||
return safe_to_return;
|
||||
}
|
||||
|
@ -1170,15 +1188,16 @@ export class Filter {
|
|||
return "/#narrow/has/reaction/sender/me";
|
||||
}
|
||||
if (_.isEqual(term_types, ["channel", "topic", "search"])) {
|
||||
const sub = stream_data.get_sub_by_id_string(this.operands("channel")[0]!);
|
||||
// if channel does not exist, redirect to home view
|
||||
if (!this._sub) {
|
||||
if (!sub) {
|
||||
return "#";
|
||||
}
|
||||
return (
|
||||
"/#narrow/" +
|
||||
CHANNEL_SYNONYM +
|
||||
"/" +
|
||||
stream_data.name_to_slug(this.operands("channel")[0]!) +
|
||||
stream_data.id_to_slug(sub.stream_id) +
|
||||
"/topic/" +
|
||||
this.operands("topic")[0]
|
||||
);
|
||||
|
@ -1191,17 +1210,16 @@ export class Filter {
|
|||
|
||||
if (term_types[1] === "search") {
|
||||
switch (term_types[0]) {
|
||||
case "channel":
|
||||
case "channel": {
|
||||
const sub = stream_data.get_sub_by_id_string(this.operands("channel")[0]!);
|
||||
// if channel does not exist, redirect to home view
|
||||
if (!this._sub) {
|
||||
if (!sub) {
|
||||
return "#";
|
||||
}
|
||||
return (
|
||||
"/#narrow/" +
|
||||
CHANNEL_SYNONYM +
|
||||
"/" +
|
||||
stream_data.name_to_slug(this.operands("channel")[0]!)
|
||||
"/#narrow/" + CHANNEL_SYNONYM + "/" + stream_data.id_to_slug(sub.stream_id)
|
||||
);
|
||||
}
|
||||
case "is-dm":
|
||||
return "/#narrow/is/dm";
|
||||
case "is-starred":
|
||||
|
@ -1250,21 +1268,23 @@ export class Filter {
|
|||
case "in-all":
|
||||
icon = "home";
|
||||
break;
|
||||
case "channel":
|
||||
if (!this._sub) {
|
||||
case "channel": {
|
||||
const sub = stream_data.get_sub_by_id_string(this.operands("channel")[0]!);
|
||||
if (!sub) {
|
||||
icon = "question-circle-o";
|
||||
break;
|
||||
}
|
||||
if (this._sub.invite_only) {
|
||||
if (sub.invite_only) {
|
||||
zulip_icon = "lock";
|
||||
break;
|
||||
}
|
||||
if (this._sub.is_web_public) {
|
||||
if (sub.is_web_public) {
|
||||
zulip_icon = "globe";
|
||||
break;
|
||||
}
|
||||
zulip_icon = "hashtag";
|
||||
break;
|
||||
}
|
||||
case "is-dm":
|
||||
zulip_icon = "user";
|
||||
break;
|
||||
|
@ -1302,11 +1322,11 @@ export class Filter {
|
|||
(term_types.length === 2 && _.isEqual(term_types, ["channel", "topic"])) ||
|
||||
(term_types.length === 1 && _.isEqual(term_types, ["channel"]))
|
||||
) {
|
||||
if (!this._sub) {
|
||||
const search_text = this.operands("channel")[0];
|
||||
return $t({defaultMessage: "Unknown channel #{search_text}"}, {search_text});
|
||||
const sub = stream_data.get_sub_by_id_string(this.operands("channel")[0]!);
|
||||
if (!sub) {
|
||||
return $t({defaultMessage: "Unknown channel"});
|
||||
}
|
||||
return this._sub.name;
|
||||
return sub.name;
|
||||
}
|
||||
if (
|
||||
(term_types.length === 2 && _.isEqual(term_types, ["dm", "near"])) ||
|
||||
|
@ -1512,8 +1532,10 @@ export class Filter {
|
|||
return new Filter(terms);
|
||||
}
|
||||
|
||||
has_topic(stream_name: string, topic: string): boolean {
|
||||
return this.has_operand("channel", stream_name) && this.has_operand("topic", topic);
|
||||
has_topic(stream_id: number, topic: string): boolean {
|
||||
return (
|
||||
this.has_operand("channel", stream_id.toString()) && this.has_operand("topic", topic)
|
||||
);
|
||||
}
|
||||
|
||||
sorted_term_types(): string[] {
|
||||
|
@ -1668,12 +1690,12 @@ export class Filter {
|
|||
this.requires_adjustment_for_moved_with_target = false;
|
||||
}
|
||||
|
||||
can_newly_match_moved_messages(new_channel: string, new_topic: string): boolean {
|
||||
can_newly_match_moved_messages(new_channel_id: string, new_topic: string): boolean {
|
||||
// Checks if any of the operators on this Filter object have
|
||||
// the property that it's possible for their true value to
|
||||
// change as a result of messages being moved into the
|
||||
// channel/topic pair provided in the parameters.
|
||||
if (this.has_operand_case_insensitive("channel", new_channel)) {
|
||||
if (this.has_operand_case_insensitive("channel", new_channel_id)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,18 +36,19 @@ export function encode_operand(operator: string, operand: string): string {
|
|||
}
|
||||
|
||||
if (operator === "stream") {
|
||||
return encode_stream_name(operand);
|
||||
const stream_id = Number.parseInt(operand, 10);
|
||||
return encode_stream_id(stream_id);
|
||||
}
|
||||
|
||||
return internal_url.encodeHashComponent(operand);
|
||||
}
|
||||
|
||||
export function encode_stream_name(operand: string): string {
|
||||
// stream_data prefixes the stream id, but it does not do the
|
||||
export function encode_stream_id(stream_id: number): string {
|
||||
// stream_data postfixes the stream name, but it does not do the
|
||||
// URI encoding piece
|
||||
operand = stream_data.name_to_slug(operand);
|
||||
const slug = stream_data.id_to_slug(stream_id);
|
||||
|
||||
return internal_url.encodeHashComponent(operand);
|
||||
return internal_url.encodeHashComponent(slug);
|
||||
}
|
||||
|
||||
export function decode_operand(operator: string, operand: string): string {
|
||||
|
@ -67,13 +68,7 @@ export function decode_operand(operator: string, operand: string): string {
|
|||
operand = internal_url.decodeHashComponent(operand);
|
||||
|
||||
if (util.canonicalize_stream_synonyms(operator) === "stream") {
|
||||
const stream_id = stream_data.slug_to_stream_id(operand);
|
||||
if (stream_id) {
|
||||
const stream = stream_data.get_sub_by_id(stream_id);
|
||||
if (stream) {
|
||||
return stream.name;
|
||||
}
|
||||
}
|
||||
return stream_data.slug_to_stream_id(operand)?.toString() ?? "";
|
||||
}
|
||||
|
||||
return operand;
|
||||
|
@ -294,7 +289,7 @@ export function validate_group_settings_hash(hash: string): string {
|
|||
|
||||
export function decode_stream_topic_from_url(
|
||||
url_str: string,
|
||||
): {stream_name: string; topic_name?: string} | null {
|
||||
): {stream_id: number; topic_name?: string} | null {
|
||||
try {
|
||||
const url = new URL(url_str);
|
||||
if (url.origin !== window.location.origin || !url.hash.startsWith("#narrow")) {
|
||||
|
@ -314,13 +309,18 @@ export function decode_stream_topic_from_url(
|
|||
if (terms[0]?.operator !== "stream" && terms[0]?.operator !== "channel") {
|
||||
return null;
|
||||
}
|
||||
const stream_id = Number.parseInt(terms[0].operand, 10);
|
||||
// This can happen if we don't recognize the stream operand as a valid id.
|
||||
if (Number.isNaN(stream_id)) {
|
||||
return null;
|
||||
}
|
||||
if (terms.length === 1) {
|
||||
return {stream_name: terms[0].operand};
|
||||
return {stream_id};
|
||||
}
|
||||
if (terms[1]?.operator !== "topic") {
|
||||
return null;
|
||||
}
|
||||
return {stream_name: terms[0].operand, topic_name: terms[1].operand};
|
||||
return {stream_id, topic_name: terms[1].operand};
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -54,7 +54,6 @@ import * as sidebar_ui from "./sidebar_ui";
|
|||
import * as spectators from "./spectators";
|
||||
import * as starred_messages_ui from "./starred_messages_ui";
|
||||
import {realm} from "./state_data";
|
||||
import * as stream_data from "./stream_data";
|
||||
import * as stream_list from "./stream_list";
|
||||
import * as stream_popover from "./stream_popover";
|
||||
import * as stream_settings_ui from "./stream_settings_ui";
|
||||
|
@ -1234,7 +1233,7 @@ export function process_hotkey(e, hotkey) {
|
|||
[
|
||||
{
|
||||
operator: "channel",
|
||||
operand: stream_data.get_stream_name_from_id(msg.stream_id),
|
||||
operand: msg.stream_id.toString(),
|
||||
},
|
||||
{operator: "topic", operand: msg.topic},
|
||||
{operator: "near", operand: msg.id},
|
||||
|
|
|
@ -472,7 +472,6 @@ export function update_messages(events) {
|
|||
});
|
||||
}
|
||||
|
||||
const old_stream_name = stream_archived ? undefined : old_stream.name;
|
||||
if (
|
||||
going_forward_change &&
|
||||
// This logic is a bit awkward. What we're trying to
|
||||
|
@ -490,7 +489,8 @@ export function update_messages(events) {
|
|||
// messages within a narrow.
|
||||
selection_changed_topic &&
|
||||
current_filter &&
|
||||
current_filter.has_topic(old_stream_name, orig_topic)
|
||||
old_stream_id &&
|
||||
current_filter.has_topic(old_stream_id, orig_topic)
|
||||
) {
|
||||
let new_filter = current_filter;
|
||||
if (new_filter && stream_changed) {
|
||||
|
@ -501,10 +501,9 @@ export function update_messages(events) {
|
|||
// stream_data lookup here to fail.
|
||||
//
|
||||
// The fix is likely somewhat involved, so punting for now.
|
||||
const new_stream_name = sub_store.get(new_stream_id).name;
|
||||
new_filter = new_filter.filter_with_new_params({
|
||||
operator: "channel",
|
||||
operand: new_stream_name,
|
||||
operand: new_stream_id.toString(),
|
||||
});
|
||||
changed_narrow = true;
|
||||
}
|
||||
|
@ -533,10 +532,10 @@ export function update_messages(events) {
|
|||
// If a message was moved to the current narrow and we don't have
|
||||
// the message cached, we need to refresh the narrow to display the message.
|
||||
if (!changed_narrow && local_cache_missing_messages && current_filter) {
|
||||
let moved_message_stream = old_stream_name;
|
||||
let moved_message_stream_id = old_stream_id;
|
||||
let moved_message_topic = orig_topic;
|
||||
if (stream_changed) {
|
||||
moved_message_stream = sub_store.get(new_stream_id).name;
|
||||
moved_message_stream_id = sub_store.get(new_stream_id).stream_id.toString();
|
||||
}
|
||||
|
||||
if (topic_edited) {
|
||||
|
@ -545,7 +544,7 @@ export function update_messages(events) {
|
|||
|
||||
if (
|
||||
current_filter.can_newly_match_moved_messages(
|
||||
moved_message_stream,
|
||||
moved_message_stream_id,
|
||||
moved_message_topic,
|
||||
)
|
||||
) {
|
||||
|
|
|
@ -340,7 +340,25 @@ export function load_messages(opts: MessageFetchOptions, attempt = 1): void {
|
|||
if (page_params.narrow !== undefined) {
|
||||
terms = [...terms, ...page_params.narrow];
|
||||
}
|
||||
data.narrow = JSON.stringify(terms);
|
||||
// TODO(stream_id): The server would ideally work with stream ids instead
|
||||
// of stream names.
|
||||
const server_terms = [];
|
||||
for (const term of terms) {
|
||||
if (term.operator === "channel") {
|
||||
const sub = stream_data.get_sub_by_id_string(term.operand);
|
||||
server_terms.push({
|
||||
...term,
|
||||
// If the sub is undefined, we'll get an error which is handled
|
||||
// later by showing a "this channel does not exist or is private"
|
||||
// notice.
|
||||
operand: sub?.name,
|
||||
});
|
||||
} else {
|
||||
server_terms.push({...term});
|
||||
}
|
||||
}
|
||||
|
||||
data.narrow = JSON.stringify(server_terms);
|
||||
}
|
||||
|
||||
let update_loading_indicator =
|
||||
|
|
|
@ -450,10 +450,11 @@ export function show(raw_terms, opts) {
|
|||
// location, then we should retarget this narrow operation
|
||||
// to where the message is located now.
|
||||
const narrow_topic = filter.operands("topic")[0];
|
||||
const narrow_stream_name = filter.operands("channel")[0];
|
||||
const narrow_stream_data = stream_data.get_sub(narrow_stream_name);
|
||||
const narrow_stream_data = stream_data.get_sub_by_id_string(
|
||||
filter.operands("channel")[0],
|
||||
);
|
||||
if (!narrow_stream_data) {
|
||||
// The stream name is invalid or incorrect in the URL.
|
||||
// The stream id is invalid or incorrect in the URL.
|
||||
// We reconstruct the narrow with the data from the
|
||||
// target message ID that we have.
|
||||
const adjusted_terms = Filter.adjusted_terms_if_moved(
|
||||
|
@ -1085,10 +1086,9 @@ export function render_message_list_with_selected_message(opts) {
|
|||
narrow_history.save_narrow_state_and_flush();
|
||||
}
|
||||
|
||||
export function activate_stream_for_cycle_hotkey(stream_id) {
|
||||
const stream_name = stream_data.get_stream_name_from_id(stream_id);
|
||||
function activate_stream_for_cycle_hotkey(stream_id) {
|
||||
// This is the common code for A/D hotkeys.
|
||||
const filter_expr = [{operator: "channel", operand: stream_name}];
|
||||
const filter_expr = [{operator: "channel", operand: stream_id.toString()}];
|
||||
show(filter_expr, {});
|
||||
}
|
||||
|
||||
|
@ -1158,9 +1158,8 @@ export function narrow_to_next_topic(opts = {}) {
|
|||
return;
|
||||
}
|
||||
|
||||
const stream_name = stream_data.get_stream_name_from_id(next_narrow.stream_id);
|
||||
const filter_expr = [
|
||||
{operator: "channel", operand: stream_name},
|
||||
{operator: "channel", operand: next_narrow.stream_id.toString()},
|
||||
{operator: "topic", operand: next_narrow.topic},
|
||||
];
|
||||
|
||||
|
@ -1218,9 +1217,8 @@ export function narrow_by_topic(target_id, opts) {
|
|||
unread_ops.notify_server_message_read(original);
|
||||
}
|
||||
|
||||
const stream_name = stream_data.get_stream_name_from_id(original.stream_id);
|
||||
const search_terms = [
|
||||
{operator: "channel", operand: stream_name},
|
||||
{operator: "channel", operand: original.stream_id.toString()},
|
||||
{operator: "topic", operand: original.topic},
|
||||
];
|
||||
opts = {then_select_id: target_id, ...opts};
|
||||
|
@ -1264,7 +1262,7 @@ export function narrow_by_recipient(target_id, opts) {
|
|||
[
|
||||
{
|
||||
operator: "stream",
|
||||
operand: stream_data.get_stream_name_from_id(message.stream_id),
|
||||
operand: message.stream_id.toString(),
|
||||
},
|
||||
],
|
||||
opts,
|
||||
|
@ -1289,10 +1287,9 @@ export function to_compose_target() {
|
|||
if (!stream_id) {
|
||||
return;
|
||||
}
|
||||
const stream_name = stream_data.get_sub_by_id(stream_id).name;
|
||||
// If we are composing to a new topic, we narrow to the stream but
|
||||
// grey-out the message view instead of narrowing to an empty view.
|
||||
const terms = [{operator: "channel", operand: stream_name}];
|
||||
const terms = [{operator: "channel", operand: stream_id.toString()}];
|
||||
const topic = compose_state.topic();
|
||||
if (topic !== "") {
|
||||
terms.push({operator: "topic", operand: topic});
|
||||
|
|
|
@ -14,6 +14,7 @@ import * as recent_view_util from "./recent_view_util";
|
|||
import * as rendered_markdown from "./rendered_markdown";
|
||||
import * as search from "./search";
|
||||
import {current_user} from "./state_data";
|
||||
import * as stream_data from "./stream_data";
|
||||
import type {SettingsSubscription} from "./stream_settings_data";
|
||||
import type {StreamSubscription} from "./sub_store";
|
||||
|
||||
|
@ -99,22 +100,21 @@ function get_message_view_header_context(filter: Filter | undefined): MessageVie
|
|||
is_spectator: page_params.is_spectator,
|
||||
});
|
||||
|
||||
if (filter.has_operator("channel") && !filter._sub) {
|
||||
return {
|
||||
...context,
|
||||
sub_count: "0",
|
||||
formatted_sub_count: "0",
|
||||
rendered_narrow_description: $t({
|
||||
defaultMessage: "This channel does not exist or is private.",
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
if (filter._sub) {
|
||||
if (filter.has_operator("channel")) {
|
||||
const current_stream = stream_data.get_sub_by_id_string(filter.operands("channel")[0]!);
|
||||
if (!current_stream) {
|
||||
return {
|
||||
...context,
|
||||
sub_count: "0",
|
||||
formatted_sub_count: "0",
|
||||
rendered_narrow_description: $t({
|
||||
defaultMessage: "This channel does not exist or is private.",
|
||||
}),
|
||||
};
|
||||
}
|
||||
// We can now be certain that the narrow
|
||||
// involves a stream which exists and
|
||||
// the current user can access.
|
||||
const current_stream = filter._sub;
|
||||
const sub_count = peer_data.get_subscriber_count(current_stream.stream_id);
|
||||
return {
|
||||
...context,
|
||||
|
@ -131,11 +131,15 @@ function get_message_view_header_context(filter: Filter | undefined): MessageVie
|
|||
|
||||
export function colorize_message_view_header(): void {
|
||||
const filter = narrow_state.filter();
|
||||
if (filter === undefined || !filter._sub) {
|
||||
let current_stream;
|
||||
if (filter?.has_operator("channel")) {
|
||||
current_stream = stream_data.get_valid_sub_by_id_string(filter.operands("channel")[0]!);
|
||||
}
|
||||
if (!current_stream) {
|
||||
return;
|
||||
}
|
||||
// selecting i instead of .fa because web public streams have custom icon.
|
||||
$("#message_view_header a.stream i").css("color", filter._sub.color);
|
||||
$("#message_view_header a.stream i").css("color", current_stream.color);
|
||||
}
|
||||
|
||||
function append_and_display_title_area(context: MessageViewHeaderContext): void {
|
||||
|
@ -175,10 +179,10 @@ export function render_title_area(): void {
|
|||
|
||||
// This function checks if "modified_sub" which is the stream whose values
|
||||
// have been updated is the same as the stream which is currently
|
||||
// narrowed (filter._sub) and rerenders if necessary
|
||||
// narrowed and rerenders if necessary
|
||||
export function maybe_rerender_title_area_for_stream(modified_sub: SettingsSubscription): void {
|
||||
const filter = narrow_state.filter();
|
||||
if (filter && filter._sub && filter._sub.stream_id === modified_sub.stream_id) {
|
||||
const current_stream_id = narrow_state.stream_id();
|
||||
if (current_stream_id === modified_sub.stream_id) {
|
||||
render_title_area();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,10 +76,11 @@ function retrieve_search_query_data(): SearchData {
|
|||
|
||||
// Add in stream:foo and topic:bar if present
|
||||
if (current_filter.has_operator("channel") || current_filter.has_operator("topic")) {
|
||||
const stream = current_filter.operands("channel")[0];
|
||||
const stream_id = current_filter.operands("channel")[0];
|
||||
const topic = current_filter.operands("topic")[0];
|
||||
if (stream) {
|
||||
search_string_result.stream_query = stream;
|
||||
if (stream_id) {
|
||||
const stream_name = stream_data.get_valid_sub_by_id_string(stream_id).name;
|
||||
search_string_result.stream_query = stream_name;
|
||||
}
|
||||
if (topic) {
|
||||
search_string_result.topic_query = topic;
|
||||
|
@ -184,7 +185,7 @@ export function pick_empty_narrow_banner(): NarrowBannerData {
|
|||
if (
|
||||
page_params.is_spectator &&
|
||||
first_operator === "channel" &&
|
||||
!stream_data.is_web_public_by_stream_name(first_operand)
|
||||
!stream_data.is_web_public_by_stream_id(Number.parseInt(first_operand, 10))
|
||||
) {
|
||||
// For non web-public streams, show `login_to_access` modal.
|
||||
spectators.login_to_access(true);
|
||||
|
@ -264,7 +265,7 @@ export function pick_empty_narrow_banner(): NarrowBannerData {
|
|||
// fallthrough to default case if no match is found
|
||||
break;
|
||||
case "channel":
|
||||
if (!stream_data.is_subscribed_by_name(first_operand)) {
|
||||
if (!stream_data.is_subscribed(Number.parseInt(first_operand, 10))) {
|
||||
// You are narrowed to a stream which does not exist or is a private stream
|
||||
// in which you were never subscribed.
|
||||
|
||||
|
@ -280,7 +281,7 @@ export function pick_empty_narrow_banner(): NarrowBannerData {
|
|||
return false;
|
||||
}
|
||||
|
||||
const stream_sub = stream_data.get_sub(first_operand);
|
||||
const stream_sub = stream_data.get_sub_by_id_string(first_operand);
|
||||
return stream_sub && stream_data.can_toggle_subscription(stream_sub);
|
||||
}
|
||||
|
||||
|
|
|
@ -114,21 +114,26 @@ export function set_compose_defaults(): {
|
|||
return opts;
|
||||
}
|
||||
|
||||
export function stream_name(current_filter: Filter | undefined = filter()): string | undefined {
|
||||
export function stream_id(current_filter: Filter | undefined = filter()): number | undefined {
|
||||
if (current_filter === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
const stream_operands = current_filter.operands("channel");
|
||||
if (stream_operands.length === 1 && stream_operands[0] !== undefined) {
|
||||
const name = stream_operands[0];
|
||||
|
||||
// Use get_name() to get the most current stream
|
||||
// name (considering renames and capitalization).
|
||||
return stream_data.get_name(name);
|
||||
return Number.parseInt(stream_operands[0], 10);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function stream_name(current_filter: Filter | undefined = filter()): string | undefined {
|
||||
const id = stream_id(current_filter);
|
||||
if (id === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
const sub = stream_data.get_sub_by_id(id);
|
||||
return sub?.name;
|
||||
}
|
||||
|
||||
export function stream_sub(
|
||||
current_filter: Filter | undefined = filter(),
|
||||
): StreamSubscription | undefined {
|
||||
|
@ -140,19 +145,7 @@ export function stream_sub(
|
|||
if (stream_operands.length !== 1 || stream_operands[0] === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const name = stream_operands[0];
|
||||
const sub = stream_data.get_sub_by_name(name);
|
||||
|
||||
return sub;
|
||||
}
|
||||
|
||||
export function stream_id(filter?: Filter): number | undefined {
|
||||
const sub = stream_sub(filter);
|
||||
if (sub === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
return sub.stream_id;
|
||||
return stream_data.get_sub_by_id_string(stream_operands[0]);
|
||||
}
|
||||
|
||||
export function topic(current_filter: Filter | undefined = filter()): string | undefined {
|
||||
|
|
|
@ -8,6 +8,7 @@ import * as inbox_util from "./inbox_util";
|
|||
import * as people from "./people";
|
||||
import * as recent_view_util from "./recent_view_util";
|
||||
import {realm} from "./state_data";
|
||||
import * as stream_data from "./stream_data";
|
||||
import * as unread from "./unread";
|
||||
import type {FullUnreadCountsData} from "./unread";
|
||||
|
||||
|
@ -34,10 +35,11 @@ export function compute_narrow_title(filter?: Filter): string {
|
|||
}
|
||||
|
||||
if (filter.has_operator("channel")) {
|
||||
if (!filter._sub) {
|
||||
const sub = stream_data.get_sub_by_id_string(filter.operands("channel")[0]!);
|
||||
if (!sub) {
|
||||
// The stream is not set because it does not currently
|
||||
// exist (possibly due to a stream name change), or it
|
||||
// is a private stream and the user is not subscribed.
|
||||
// exist, or it is a private stream and the user is not
|
||||
// subscribed.
|
||||
return filter_title;
|
||||
}
|
||||
if (filter.has_operator("topic")) {
|
||||
|
|
|
@ -8,7 +8,6 @@ import {$t} from "./i18n";
|
|||
import * as message_view from "./message_view";
|
||||
import * as people from "./people";
|
||||
import * as scheduled_messages from "./scheduled_messages";
|
||||
import * as stream_data from "./stream_data";
|
||||
import * as timerender from "./timerender";
|
||||
|
||||
export function hide_scheduled_message_success_compose_banner(scheduled_message_id) {
|
||||
|
@ -23,7 +22,7 @@ function narrow_via_edit_scheduled_message(compose_args) {
|
|||
[
|
||||
{
|
||||
operator: "channel",
|
||||
operand: stream_data.get_stream_name_from_id(compose_args.stream_id),
|
||||
operand: compose_args.stream_id,
|
||||
},
|
||||
{operator: "topic", operand: compose_args.topic},
|
||||
],
|
||||
|
|
|
@ -10,6 +10,7 @@ import type {InputPill, InputPillContainer} from "./input_pill";
|
|||
import * as people from "./people";
|
||||
import type {User} from "./people";
|
||||
import type {NarrowTerm} from "./state_data";
|
||||
import * as stream_data from "./stream_data";
|
||||
import * as user_status from "./user_status";
|
||||
import type {UserStatusEmojiInfo} from "./user_status";
|
||||
import * as util from "./util";
|
||||
|
@ -56,7 +57,7 @@ export function create_item_from_search_string(search_string: string): SearchPil
|
|||
|
||||
export function get_search_string_from_item(item: SearchPill): string {
|
||||
const sign = item.negated ? "-" : "";
|
||||
return `${sign}${item.operator}: ${get_search_operand(item)}`;
|
||||
return `${sign}${item.operator}: ${get_search_operand(item, true)}`;
|
||||
}
|
||||
|
||||
// This is called when the a pill is closed. We have custom logic here
|
||||
|
@ -215,16 +216,19 @@ export function set_search_bar_contents(
|
|||
}
|
||||
}
|
||||
|
||||
function get_search_operand(item: SearchPill): string {
|
||||
function get_search_operand(item: SearchPill, for_display: boolean): string {
|
||||
if (item.type === "search_user") {
|
||||
return item.users.map((user) => user.email).join(",");
|
||||
}
|
||||
if (for_display && item.operator === "channel") {
|
||||
return stream_data.get_valid_sub_by_id_string(item.operand).name;
|
||||
}
|
||||
return item.operand;
|
||||
}
|
||||
|
||||
export function get_current_search_pill_terms(pill_widget: SearchPillWidget): NarrowTerm[] {
|
||||
return pill_widget.items().map((item) => ({
|
||||
...item,
|
||||
operand: get_search_operand(item),
|
||||
operand: get_search_operand(item, false),
|
||||
}));
|
||||
}
|
||||
|
|
|
@ -159,21 +159,23 @@ function get_channel_suggestions(last: NarrowTerm, terms: NarrowTerm[]): Suggest
|
|||
const query = last.operand;
|
||||
let channels = stream_data.subscribed_streams();
|
||||
|
||||
channels = channels.filter((channel) => channel_matches_query(channel, query));
|
||||
channels = channels.filter((channel_name) => channel_matches_query(channel_name, query));
|
||||
|
||||
channels = typeahead_helper.sorter(query, channels, (x) => x);
|
||||
|
||||
const regex = typeahead_helper.build_highlight_regex(query);
|
||||
const highlight_query = typeahead_helper.highlight_with_escaping_and_regex;
|
||||
|
||||
return channels.map((channel) => {
|
||||
return channels.map((channel_name) => {
|
||||
const prefix = "channel";
|
||||
const highlighted_channel = highlight_query(regex, channel);
|
||||
const highlighted_channel = highlight_query(regex, channel_name);
|
||||
const verb = last.negated ? "exclude " : "";
|
||||
const description_html = verb + prefix + " " + highlighted_channel;
|
||||
const channel = stream_data.get_sub_by_name(channel_name);
|
||||
assert(channel !== undefined);
|
||||
const term = {
|
||||
operator: "channel",
|
||||
operand: channel,
|
||||
operand: channel.stream_id.toString(),
|
||||
negated: last.negated,
|
||||
};
|
||||
const search_string = Filter.unparse([term]);
|
||||
|
@ -473,7 +475,7 @@ function get_topic_suggestions(last: NarrowTerm, terms: NarrowTerm[]): Suggestio
|
|||
const operator = Filter.canonicalize_operator(last.operator);
|
||||
const operand = last.operand;
|
||||
const negated = operator === "topic" && last.negated;
|
||||
let channel: string | undefined;
|
||||
let channel_id: string | undefined;
|
||||
let guess: string | undefined;
|
||||
const filter = new Filter(terms);
|
||||
const suggest_terms: NarrowTerm[] = [];
|
||||
|
@ -496,28 +498,28 @@ function get_topic_suggestions(last: NarrowTerm, terms: NarrowTerm[]): Suggestio
|
|||
switch (operator) {
|
||||
case "channel":
|
||||
guess = "";
|
||||
channel = operand;
|
||||
channel_id = operand;
|
||||
suggest_terms.push(last);
|
||||
break;
|
||||
case "topic":
|
||||
case "search":
|
||||
guess = operand;
|
||||
if (filter.has_operator("channel")) {
|
||||
channel = filter.operands("channel")[0];
|
||||
channel_id = filter.operands("channel")[0];
|
||||
} else {
|
||||
channel = narrow_state.stream_name();
|
||||
if (channel) {
|
||||
suggest_terms.push({operator: "channel", operand: channel});
|
||||
channel_id = narrow_state.stream_id()?.toString();
|
||||
if (channel_id) {
|
||||
suggest_terms.push({operator: "channel", operand: channel_id});
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!channel) {
|
||||
if (!channel_id) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const subscription = stream_data.get_sub(channel);
|
||||
const subscription = stream_data.get_sub_by_id_string(channel_id);
|
||||
if (!subscription) {
|
||||
return [];
|
||||
}
|
||||
|
@ -849,12 +851,12 @@ function suggestion_search_string(suggestion_line: SuggestionLine): string {
|
|||
}
|
||||
|
||||
function suggestions_for_current_filter(): SuggestionLine[] {
|
||||
if (narrow_state.stream_name() && narrow_state.topic() !== "") {
|
||||
if (narrow_state.stream_id() && narrow_state.topic() !== "") {
|
||||
return [
|
||||
get_default_suggestion_line([
|
||||
{
|
||||
operator: "channel",
|
||||
operand: narrow_state.stream_name()!,
|
||||
operand: narrow_state.stream_id()!.toString(),
|
||||
},
|
||||
]),
|
||||
get_default_suggestion_line(narrow_state.search_terms()),
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import assert from "minimalistic-assert";
|
||||
|
||||
import * as blueslip from "./blueslip";
|
||||
import * as color_data from "./color_data";
|
||||
import {FoldDict} from "./fold_dict";
|
||||
|
@ -177,6 +179,18 @@ export function get_sub(stream_name: string): StreamSubscription | undefined {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
export function get_sub_by_id_string(stream_id_string: string): StreamSubscription | undefined {
|
||||
const stream_id = Number.parseInt(stream_id_string, 10);
|
||||
const stream = stream_info.get(stream_id);
|
||||
return stream;
|
||||
}
|
||||
|
||||
export function get_valid_sub_by_id_string(stream_id_string: string): StreamSubscription {
|
||||
const stream = get_sub_by_id_string(stream_id_string);
|
||||
assert(stream !== undefined);
|
||||
return stream;
|
||||
}
|
||||
|
||||
export function get_sub_by_id(stream_id: number): StreamSubscription | undefined {
|
||||
return stream_info.get(stream_id);
|
||||
}
|
||||
|
@ -222,13 +236,8 @@ export function get_sub_by_name(name: string): StreamSubscription | undefined {
|
|||
return sub_store.get(stream_id);
|
||||
}
|
||||
|
||||
export function name_to_slug(name: string): string {
|
||||
const stream_id = get_stream_id(name);
|
||||
|
||||
if (!stream_id) {
|
||||
return name;
|
||||
}
|
||||
|
||||
export function id_to_slug(stream_id: number): string {
|
||||
let name = get_stream_name_from_id(stream_id);
|
||||
// The name part of the URL doesn't really matter, so we try to
|
||||
// make it pretty.
|
||||
name = name.replaceAll(" ", "-");
|
||||
|
@ -605,11 +614,6 @@ export function can_post_messages_in_stream(stream: StreamSubscription): boolean
|
|||
return true;
|
||||
}
|
||||
|
||||
export function is_subscribed_by_name(stream_name: string): boolean {
|
||||
const sub = get_sub(stream_name);
|
||||
return sub ? sub.subscribed : false;
|
||||
}
|
||||
|
||||
export function is_subscribed(stream_id: number): boolean {
|
||||
const sub = sub_store.get(stream_id);
|
||||
return sub ? sub.subscribed : false;
|
||||
|
@ -643,8 +647,8 @@ export function is_invite_only_by_stream_id(stream_id: number): boolean {
|
|||
return sub.invite_only;
|
||||
}
|
||||
|
||||
export function is_web_public_by_stream_name(stream_name: string): boolean {
|
||||
const sub = get_sub(stream_name);
|
||||
export function is_web_public_by_stream_id(stream_id: number): boolean {
|
||||
const sub = get_sub_by_id(stream_id);
|
||||
if (sub === undefined) {
|
||||
return false;
|
||||
}
|
||||
|
@ -667,22 +671,6 @@ export function is_default_stream_id(stream_id: number): boolean {
|
|||
return default_stream_ids.has(stream_id);
|
||||
}
|
||||
|
||||
export function get_name(stream_name: string): string {
|
||||
// This returns the actual name of a stream if we are subscribed to
|
||||
// it (e.g. "Denmark" vs. "denmark"), while falling thru to
|
||||
// stream_name if we don't have a subscription. (Stream names
|
||||
// are case-insensitive, but we try to display the actual name
|
||||
// when we know it.)
|
||||
//
|
||||
// This function will also do the right thing if we have
|
||||
// an old stream name in memory for a recently renamed stream.
|
||||
const sub = get_sub_by_name(stream_name);
|
||||
if (sub === undefined) {
|
||||
return stream_name;
|
||||
}
|
||||
return sub.name;
|
||||
}
|
||||
|
||||
export function is_user_subscribed(stream_id: number, user_id: number): boolean {
|
||||
const sub = sub_store.get(stream_id);
|
||||
if (sub === undefined || !can_view_subscribers(sub)) {
|
||||
|
|
|
@ -682,8 +682,7 @@ export function get_sidebar_stream_topic_info(filter: Filter): {
|
|||
return result;
|
||||
}
|
||||
|
||||
const stream_name = op_stream[0];
|
||||
const stream_id = stream_data.get_stream_id(stream_name);
|
||||
const stream_id = Number.parseInt(op_stream[0], 10);
|
||||
|
||||
if (!stream_id) {
|
||||
return result;
|
||||
|
|
|
@ -138,7 +138,7 @@ function build_stream_popover(opts) {
|
|||
[
|
||||
{
|
||||
operator: "stream",
|
||||
operand: sub.name,
|
||||
operand: sub.stream_id.toString(),
|
||||
},
|
||||
],
|
||||
{trigger: "stream-popover"},
|
||||
|
|
|
@ -903,7 +903,7 @@ export function view_stream() {
|
|||
const row_data = get_row_data(active_data.$row);
|
||||
if (row_data) {
|
||||
const stream_narrow_hash =
|
||||
"#narrow/stream/" + hash_util.encode_stream_name(row_data.object.name);
|
||||
"#narrow/stream/" + hash_util.encode_stream_id(row_data.object.stream_id);
|
||||
browser_history.go_to_location(stream_narrow_hash);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import _ from "lodash";
|
||||
import assert from "minimalistic-assert";
|
||||
|
||||
import * as narrow_state from "./narrow_state";
|
||||
import * as pm_conversations from "./pm_conversations";
|
||||
|
@ -87,7 +86,6 @@ export function get_next_topic(
|
|||
|
||||
function get_unmuted_topics(stream_id: number): string[] {
|
||||
const narrowed_steam_id = narrow_state.stream_id();
|
||||
assert(stream_id !== undefined);
|
||||
const topics = stream_topic_history.get_recent_topic_names(stream_id);
|
||||
const narrowed_topic = narrow_state.topic();
|
||||
if (
|
||||
|
@ -119,16 +117,11 @@ export function get_next_topic(
|
|||
return topics;
|
||||
}
|
||||
|
||||
function has_unread_messages(stream_id: number, topic: string): boolean {
|
||||
assert(stream_id !== undefined);
|
||||
return unread.topic_has_any_unread(stream_id, topic);
|
||||
}
|
||||
|
||||
if (only_followed_topics) {
|
||||
return next_topic(
|
||||
my_streams,
|
||||
get_followed_topics,
|
||||
has_unread_messages,
|
||||
unread.topic_has_any_unread,
|
||||
curr_stream_id,
|
||||
curr_topic,
|
||||
);
|
||||
|
@ -137,7 +130,7 @@ export function get_next_topic(
|
|||
return next_topic(
|
||||
my_streams,
|
||||
get_unmuted_topics,
|
||||
has_unread_messages,
|
||||
unread.topic_has_any_unread,
|
||||
curr_stream_id,
|
||||
curr_topic,
|
||||
);
|
||||
|
|
|
@ -549,7 +549,7 @@ export function initialize_everything(state_data) {
|
|||
[
|
||||
{
|
||||
operator: "stream",
|
||||
operand: sub.name,
|
||||
operand: sub.stream_id.toString(),
|
||||
},
|
||||
],
|
||||
{trigger},
|
||||
|
@ -658,7 +658,7 @@ export function initialize_everything(state_data) {
|
|||
const sub = sub_store.get(stream_id);
|
||||
message_view.show(
|
||||
[
|
||||
{operator: "channel", operand: sub.name},
|
||||
{operator: "channel", operand: sub.stream_id.toString()},
|
||||
{operator: "topic", operand: topic},
|
||||
],
|
||||
{trigger: "sidebar"},
|
||||
|
|
|
@ -22,7 +22,6 @@ import * as overlays from "./overlays";
|
|||
import * as people from "./people";
|
||||
import * as recent_view_ui from "./recent_view_ui";
|
||||
import type {NarrowTerm} from "./state_data";
|
||||
import * as stream_data from "./stream_data";
|
||||
import * as ui_report from "./ui_report";
|
||||
import * as unread from "./unread";
|
||||
import * as unread_ui from "./unread_ui";
|
||||
|
@ -610,22 +609,20 @@ export function process_visible(): void {
|
|||
}
|
||||
|
||||
export function mark_stream_as_read(stream_id: number): void {
|
||||
const stream_name = stream_data.get_stream_name_from_id(stream_id);
|
||||
bulk_update_read_flags_for_narrow(
|
||||
[
|
||||
{operator: "is", operand: "unread", negated: false},
|
||||
{operator: "channel", operand: stream_name},
|
||||
{operator: "channel", operand: stream_id.toString()},
|
||||
],
|
||||
"add",
|
||||
);
|
||||
}
|
||||
|
||||
export function mark_topic_as_read(stream_id: number, topic: string): void {
|
||||
const stream_name = stream_data.get_stream_name_from_id(stream_id);
|
||||
bulk_update_read_flags_for_narrow(
|
||||
[
|
||||
{operator: "is", operand: "unread", negated: false},
|
||||
{operator: "channel", operand: stream_name},
|
||||
{operator: "channel", operand: stream_id.toString()},
|
||||
{operator: "topic", operand: topic},
|
||||
],
|
||||
"add",
|
||||
|
@ -633,10 +630,9 @@ export function mark_topic_as_read(stream_id: number, topic: string): void {
|
|||
}
|
||||
|
||||
export function mark_topic_as_unread(stream_id: number, topic: string): void {
|
||||
const stream_name = stream_data.get_stream_name_from_id(stream_id);
|
||||
bulk_update_read_flags_for_narrow(
|
||||
[
|
||||
{operator: "channel", operand: stream_name},
|
||||
{operator: "channel", operand: stream_id.toString()},
|
||||
{operator: "topic", operand: topic},
|
||||
],
|
||||
"remove",
|
||||
|
|
|
@ -105,7 +105,7 @@ const $fred_stub = $.create("fred stub");
|
|||
const rome_sub = {name: "Rome", subscribed: true, stream_id: 1001};
|
||||
function add_sub_and_set_as_current_narrow(sub) {
|
||||
stream_data.add_sub(sub);
|
||||
const filter = new Filter([{operator: "stream", operand: sub.name}]);
|
||||
const filter = new Filter([{operator: "stream", operand: sub.stream_id}]);
|
||||
message_lists.set_current({
|
||||
data: {
|
||||
filter,
|
||||
|
|
|
@ -34,7 +34,7 @@ run_test("filter", () => {
|
|||
stream_data.add_sub(denmark_stream);
|
||||
|
||||
const filter_terms = [
|
||||
{operator: "stream", operand: "Denmark"},
|
||||
{operator: "stream", operand: denmark_stream.stream_id.toString()},
|
||||
{operator: "topic", operand: "copenhagen"},
|
||||
];
|
||||
|
||||
|
@ -85,7 +85,7 @@ run_test("narrow_state", () => {
|
|||
|
||||
// Now set up a Filter object.
|
||||
const filter_terms = [
|
||||
{operator: "stream", operand: "Denmark"},
|
||||
{operator: "stream", operand: denmark_stream.stream_id.toString()},
|
||||
{operator: "topic", operand: "copenhagen"},
|
||||
];
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -21,8 +21,9 @@ const hamlet = {
|
|||
|
||||
people.add_active_user(hamlet);
|
||||
|
||||
const frontend_id = 99;
|
||||
const frontend = {
|
||||
stream_id: 99,
|
||||
stream_id: frontend_id,
|
||||
name: "frontend",
|
||||
};
|
||||
|
||||
|
@ -44,7 +45,7 @@ run_test("hash_util", () => {
|
|||
encode_decode_operand(operator, operand, "15-Hamlet");
|
||||
|
||||
operator = "stream";
|
||||
operand = "frontend";
|
||||
operand = frontend_id.toString();
|
||||
|
||||
encode_decode_operand(operator, operand, "99-frontend");
|
||||
|
||||
|
@ -175,19 +176,19 @@ run_test("test_is_in_specified_hash_category", () => {
|
|||
|
||||
run_test("test_parse_narrow", () => {
|
||||
assert.deepEqual(hash_util.parse_narrow(["narrow", "stream", "99-frontend"]), [
|
||||
{negated: false, operator: "stream", operand: "frontend"},
|
||||
{negated: false, operator: "stream", operand: frontend_id.toString()},
|
||||
]);
|
||||
|
||||
assert.deepEqual(hash_util.parse_narrow(["narrow", "-stream", "99-frontend"]), [
|
||||
{negated: true, operator: "stream", operand: "frontend"},
|
||||
{negated: true, operator: "stream", operand: frontend_id.toString()},
|
||||
]);
|
||||
|
||||
assert.equal(hash_util.parse_narrow(["narrow", "BOGUS"]), undefined);
|
||||
|
||||
// For nonexistent streams, we get the full slug.
|
||||
// We possibly should remove the prefix and fix this test.
|
||||
// For nonexistent streams, we get an empty string. We don't use this
|
||||
// anywhere, and just show "Invalid stream" in the navbar.
|
||||
assert.deepEqual(hash_util.parse_narrow(["narrow", "stream", "42-bogus"]), [
|
||||
{negated: false, operator: "stream", operand: "42-bogus"},
|
||||
{negated: false, operator: "stream", operand: ""},
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
|
@ -38,48 +38,60 @@ const message_view = zrequire("../src/message_view");
|
|||
const stream_data = zrequire("stream_data");
|
||||
const {Filter} = zrequire("../src/filter");
|
||||
|
||||
const devel_id = 100;
|
||||
const devel = {
|
||||
name: "devel",
|
||||
stream_id: devel_id,
|
||||
color: "blue",
|
||||
subscribed: true,
|
||||
};
|
||||
stream_data.add_sub(devel);
|
||||
|
||||
run_test("terms_round_trip", () => {
|
||||
let terms;
|
||||
let hash;
|
||||
let narrow;
|
||||
|
||||
terms = [
|
||||
{operator: "stream", operand: "devel"},
|
||||
{operator: "stream", operand: devel_id.toString()},
|
||||
{operator: "topic", operand: "algol"},
|
||||
];
|
||||
hash = hash_util.search_terms_to_hash(terms);
|
||||
assert.equal(hash, "#narrow/stream/devel/topic/algol");
|
||||
assert.equal(hash, "#narrow/stream/100-devel/topic/algol");
|
||||
|
||||
narrow = hash_util.parse_narrow(hash.split("/"));
|
||||
assert.deepEqual(narrow, [
|
||||
{operator: "stream", operand: "devel", negated: false},
|
||||
{operator: "stream", operand: devel_id.toString(), negated: false},
|
||||
{operator: "topic", operand: "algol", negated: false},
|
||||
]);
|
||||
|
||||
terms = [
|
||||
{operator: "stream", operand: "devel"},
|
||||
{operator: "stream", operand: devel_id.toString()},
|
||||
{operator: "topic", operand: "visual c++", negated: true},
|
||||
];
|
||||
hash = hash_util.search_terms_to_hash(terms);
|
||||
assert.equal(hash, "#narrow/stream/devel/-topic/visual.20c.2B.2B");
|
||||
assert.equal(hash, "#narrow/stream/100-devel/-topic/visual.20c.2B.2B");
|
||||
|
||||
narrow = hash_util.parse_narrow(hash.split("/"));
|
||||
assert.deepEqual(narrow, [
|
||||
{operator: "stream", operand: "devel", negated: false},
|
||||
{operator: "stream", operand: devel_id.toString(), negated: false},
|
||||
{operator: "topic", operand: "visual c++", negated: true},
|
||||
]);
|
||||
|
||||
// test new encodings, where we have a stream id
|
||||
const florida_id = 987;
|
||||
const florida_stream = {
|
||||
name: "Florida, USA",
|
||||
stream_id: 987,
|
||||
stream_id: florida_id,
|
||||
};
|
||||
stream_data.add_sub(florida_stream);
|
||||
terms = [{operator: "stream", operand: "Florida, USA"}];
|
||||
terms = [{operator: "stream", operand: florida_id.toString()}];
|
||||
hash = hash_util.search_terms_to_hash(terms);
|
||||
assert.equal(hash, "#narrow/stream/987-Florida.2C-USA");
|
||||
narrow = hash_util.parse_narrow(hash.split("/"));
|
||||
assert.deepEqual(narrow, [{operator: "stream", operand: "Florida, USA", negated: false}]);
|
||||
assert.deepEqual(narrow, [
|
||||
{operator: "stream", operand: florida_id.toString(), negated: false},
|
||||
]);
|
||||
});
|
||||
|
||||
run_test("stream_to_channel_rename", () => {
|
||||
|
@ -90,13 +102,15 @@ run_test("stream_to_channel_rename", () => {
|
|||
|
||||
// Confirm the URLs generated from search terms use "stream" and "streams"
|
||||
// and that the new Filter has the new "channel" and "channels" operators.
|
||||
terms = [{operator: "channel", operand: "devel"}];
|
||||
terms = [{operator: "channel", operand: devel_id.toString()}];
|
||||
hash = hash_util.search_terms_to_hash(terms);
|
||||
assert.equal(hash, "#narrow/stream/devel");
|
||||
assert.equal(hash, "#narrow/stream/100-devel");
|
||||
narrow = hash_util.parse_narrow(hash.split("/"));
|
||||
assert.deepEqual(narrow, [{operator: "stream", operand: "devel", negated: false}]);
|
||||
assert.deepEqual(narrow, [{operator: "stream", operand: devel_id.toString(), negated: false}]);
|
||||
filter = new Filter(narrow);
|
||||
assert.deepEqual(filter.terms(), [{operator: "channel", operand: "devel", negated: false}]);
|
||||
assert.deepEqual(filter.terms(), [
|
||||
{operator: "channel", operand: devel_id.toString(), negated: false},
|
||||
]);
|
||||
|
||||
terms = [{operator: "channels", operand: "public"}];
|
||||
hash = hash_util.search_terms_to_hash(terms);
|
||||
|
@ -108,23 +122,28 @@ run_test("stream_to_channel_rename", () => {
|
|||
|
||||
// Confirm that a narrow URL with "channel" and an enocoded stream/channel ID,
|
||||
// will be decoded correctly.
|
||||
const test_stream_id = 34;
|
||||
const test_channel = {
|
||||
name: "decode",
|
||||
stream_id: 34,
|
||||
stream_id: test_stream_id,
|
||||
};
|
||||
stream_data.add_sub(test_channel);
|
||||
hash = "#narrow/channel/34-decode";
|
||||
narrow = hash_util.parse_narrow(hash.split("/"));
|
||||
assert.deepEqual(narrow, [{operator: "channel", operand: "decode", negated: false}]);
|
||||
assert.deepEqual(narrow, [
|
||||
{operator: "channel", operand: test_stream_id.toString(), negated: false},
|
||||
]);
|
||||
filter = new Filter(narrow);
|
||||
assert.deepEqual(filter.terms(), [{operator: "channel", operand: "decode", negated: false}]);
|
||||
assert.deepEqual(filter.terms(), [
|
||||
{operator: "channel", operand: test_stream_id.toString(), negated: false},
|
||||
]);
|
||||
});
|
||||
|
||||
run_test("terms_trailing_slash", () => {
|
||||
const hash = "#narrow/stream/devel/topic/algol/";
|
||||
const hash = "#narrow/stream/100-devel/topic/algol/";
|
||||
const narrow = hash_util.parse_narrow(hash.split("/"));
|
||||
assert.deepEqual(narrow, [
|
||||
{operator: "stream", operand: "devel", negated: false},
|
||||
{operator: "stream", operand: devel_id.toString(), negated: false},
|
||||
{operator: "topic", operand: "algol", negated: false},
|
||||
]);
|
||||
});
|
||||
|
@ -270,6 +289,12 @@ run_test("hash_interactions", ({override, override_rewire}) => {
|
|||
]);
|
||||
assert.equal(window.location.hash, "#recent");
|
||||
|
||||
const denmark_id = 1;
|
||||
stream_data.add_sub({
|
||||
subscribed: true,
|
||||
name: "Denmark",
|
||||
stream_id: denmark_id,
|
||||
});
|
||||
window.location.hash = "#narrow/stream/Denmark";
|
||||
|
||||
helper.clear_events();
|
||||
|
@ -280,7 +305,7 @@ run_test("hash_interactions", ({override, override_rewire}) => {
|
|||
"message_view.show",
|
||||
]);
|
||||
let terms = helper.get_narrow_terms();
|
||||
assert.equal(terms[0].operand, "Denmark");
|
||||
assert.equal(terms[0].operand, denmark_id.toString());
|
||||
|
||||
window.location.hash = "#narrow";
|
||||
|
||||
|
|
|
@ -242,7 +242,7 @@ run_test("show_empty_narrow_message", ({mock_template}) => {
|
|||
);
|
||||
|
||||
// for non-existent or private stream
|
||||
set_filter([["stream", "Foo"]]);
|
||||
set_filter([["stream", "999"]]);
|
||||
narrow_banner.show_empty_narrow_message();
|
||||
assert.equal(
|
||||
$(".empty_feed_notice_main").html(),
|
||||
|
@ -250,8 +250,9 @@ run_test("show_empty_narrow_message", ({mock_template}) => {
|
|||
);
|
||||
|
||||
// for non-subbed public stream
|
||||
stream_data.add_sub({name: "ROME", stream_id: 99});
|
||||
set_filter([["stream", "Rome"]]);
|
||||
const rome_id = 99;
|
||||
stream_data.add_sub({name: "ROME", stream_id: rome_id});
|
||||
set_filter([["stream", rome_id.toString()]]);
|
||||
narrow_banner.show_empty_narrow_message();
|
||||
assert.equal(
|
||||
$(".empty_feed_notice_main").html(),
|
||||
|
@ -263,7 +264,7 @@ run_test("show_empty_narrow_message", ({mock_template}) => {
|
|||
|
||||
// for non-web-public stream for spectator
|
||||
page_params.is_spectator = true;
|
||||
set_filter([["stream", "Rome"]]);
|
||||
set_filter([["stream", rome_id.toString()]]);
|
||||
narrow_banner.show_empty_narrow_message();
|
||||
assert.equal(
|
||||
$(".empty_feed_notice_main").html(),
|
||||
|
@ -274,7 +275,7 @@ run_test("show_empty_narrow_message", ({mock_template}) => {
|
|||
);
|
||||
|
||||
set_filter([
|
||||
["stream", "Rome"],
|
||||
["stream", rome_id.toString()],
|
||||
["topic", "foo"],
|
||||
]);
|
||||
narrow_banner.show_empty_narrow_message();
|
||||
|
@ -287,9 +288,10 @@ run_test("show_empty_narrow_message", ({mock_template}) => {
|
|||
);
|
||||
|
||||
// for web-public stream for spectator
|
||||
stream_data.add_sub({name: "web-public-stream", stream_id: 1231, is_web_public: true});
|
||||
const web_public_id = 1231;
|
||||
stream_data.add_sub({name: "web-public-stream", stream_id: web_public_id, is_web_public: true});
|
||||
set_filter([
|
||||
["stream", "web-public-stream"],
|
||||
["stream", web_public_id.toString()],
|
||||
["topic", "foo"],
|
||||
]);
|
||||
narrow_banner.show_empty_narrow_message();
|
||||
|
@ -524,7 +526,7 @@ run_test("show_empty_narrow_message", ({mock_template}) => {
|
|||
|
||||
set_filter([
|
||||
["sender", "alice@example.com"],
|
||||
["stream", "Rome"],
|
||||
["stream", rome_id.toString()],
|
||||
]);
|
||||
narrow_banner.show_empty_narrow_message();
|
||||
assert.equal(
|
||||
|
@ -542,14 +544,15 @@ run_test("show_empty_narrow_message", ({mock_template}) => {
|
|||
),
|
||||
);
|
||||
|
||||
const my_stream_id = 103;
|
||||
const my_stream = {
|
||||
name: "my stream",
|
||||
stream_id: 103,
|
||||
stream_id: my_stream_id,
|
||||
};
|
||||
stream_data.add_sub(my_stream);
|
||||
stream_data.subscribe_myself(my_stream);
|
||||
|
||||
set_filter([["stream", "my stream"]]);
|
||||
set_filter([["stream", my_stream_id.toString()]]);
|
||||
narrow_banner.show_empty_narrow_message();
|
||||
assert.equal(
|
||||
$(".empty_feed_notice_main").html(),
|
||||
|
@ -617,6 +620,8 @@ run_test("show_search_stopwords", ({mock_template}) => {
|
|||
empty_narrow_html("translated: No search results.", undefined, expected_search_data),
|
||||
);
|
||||
|
||||
const streamA_id = 88;
|
||||
stream_data.add_sub({name: "streamA", stream_id: streamA_id});
|
||||
const expected_stream_search_data = {
|
||||
has_stop_word: true,
|
||||
stream_query: "streamA",
|
||||
|
@ -627,7 +632,7 @@ run_test("show_search_stopwords", ({mock_template}) => {
|
|||
],
|
||||
};
|
||||
set_filter([
|
||||
["stream", "streamA"],
|
||||
["stream", streamA_id.toString()],
|
||||
["search", "what about grail"],
|
||||
]);
|
||||
narrow_banner.show_empty_narrow_message();
|
||||
|
@ -647,7 +652,7 @@ run_test("show_search_stopwords", ({mock_template}) => {
|
|||
],
|
||||
};
|
||||
set_filter([
|
||||
["stream", "streamA"],
|
||||
["stream", streamA_id.toString()],
|
||||
["topic", "topicA"],
|
||||
["search", "what about grail"],
|
||||
]);
|
||||
|
@ -666,12 +671,14 @@ run_test("show_invalid_narrow_message", ({mock_template}) => {
|
|||
message_lists.set_current(undefined);
|
||||
mock_template("empty_feed_notice.hbs", true, (_data, html) => html);
|
||||
|
||||
stream_data.add_sub({name: "streamA", stream_id: 88});
|
||||
stream_data.add_sub({name: "streamB", stream_id: 77});
|
||||
const streamA_id = 88;
|
||||
const streamB_id = 77;
|
||||
stream_data.add_sub({name: "streamA", stream_id: streamA_id});
|
||||
stream_data.add_sub({name: "streamB", stream_id: streamB_id});
|
||||
|
||||
set_filter([
|
||||
["stream", "streamA"],
|
||||
["stream", "streamB"],
|
||||
["stream", streamA_id.toString()],
|
||||
["stream", streamB_id.toString()],
|
||||
]);
|
||||
narrow_banner.show_empty_narrow_message();
|
||||
assert.equal(
|
||||
|
@ -734,7 +741,8 @@ run_test("narrow_to_compose_target streams", ({override_rewire}) => {
|
|||
});
|
||||
|
||||
compose_state.set_message_type("stream");
|
||||
stream_data.add_sub({name: "ROME", stream_id: 99});
|
||||
const rome_id = 99;
|
||||
stream_data.add_sub({name: "ROME", stream_id: rome_id});
|
||||
compose_state.set_stream_id(99);
|
||||
|
||||
// Test with existing topic
|
||||
|
@ -744,7 +752,7 @@ run_test("narrow_to_compose_target streams", ({override_rewire}) => {
|
|||
assert.equal(args.called, true);
|
||||
assert.equal(args.opts.trigger, "narrow_to_compose_target");
|
||||
assert.deepEqual(args.terms, [
|
||||
{operator: "channel", operand: "ROME"},
|
||||
{operator: "channel", operand: rome_id.toString()},
|
||||
{operator: "topic", operand: "one"},
|
||||
]);
|
||||
|
||||
|
@ -754,7 +762,7 @@ run_test("narrow_to_compose_target streams", ({override_rewire}) => {
|
|||
message_view.to_compose_target();
|
||||
assert.equal(args.called, true);
|
||||
assert.deepEqual(args.terms, [
|
||||
{operator: "channel", operand: "ROME"},
|
||||
{operator: "channel", operand: rome_id.toString()},
|
||||
{operator: "topic", operand: "four"},
|
||||
]);
|
||||
|
||||
|
@ -763,14 +771,14 @@ run_test("narrow_to_compose_target streams", ({override_rewire}) => {
|
|||
args.called = false;
|
||||
message_view.to_compose_target();
|
||||
assert.equal(args.called, true);
|
||||
assert.deepEqual(args.terms, [{operator: "channel", operand: "ROME"}]);
|
||||
assert.deepEqual(args.terms, [{operator: "channel", operand: rome_id.toString()}]);
|
||||
|
||||
// Test with no topic
|
||||
compose_state.topic(undefined);
|
||||
args.called = false;
|
||||
message_view.to_compose_target();
|
||||
assert.equal(args.called, true);
|
||||
assert.deepEqual(args.terms, [{operator: "channel", operand: "ROME"}]);
|
||||
assert.deepEqual(args.terms, [{operator: "channel", operand: rome_id.toString()}]);
|
||||
});
|
||||
|
||||
run_test("narrow_to_compose_target direct messages", ({override, override_rewire}) => {
|
||||
|
@ -851,26 +859,24 @@ run_test("narrow_compute_title", () => {
|
|||
assert.equal(narrow_title.compute_narrow_title(filter), "translated: Messages sent by you");
|
||||
|
||||
// Stream narrows
|
||||
const foo_stream_id = 43;
|
||||
const sub = {
|
||||
name: "Foo",
|
||||
stream_id: 43,
|
||||
stream_id: foo_stream_id,
|
||||
};
|
||||
stream_data.add_sub(sub);
|
||||
|
||||
filter = new Filter([
|
||||
{operator: "stream", operand: "foo"},
|
||||
{operator: "stream", operand: foo_stream_id.toString()},
|
||||
{operator: "topic", operand: "bar"},
|
||||
]);
|
||||
assert.equal(narrow_title.compute_narrow_title(filter), "#Foo > bar");
|
||||
|
||||
filter = new Filter([{operator: "stream", operand: "foo"}]);
|
||||
filter = new Filter([{operator: "stream", operand: foo_stream_id.toString()}]);
|
||||
assert.equal(narrow_title.compute_narrow_title(filter), "#Foo");
|
||||
|
||||
filter = new Filter([{operator: "stream", operand: "Elephant"}]);
|
||||
assert.equal(
|
||||
narrow_title.compute_narrow_title(filter),
|
||||
"translated: Unknown channel #Elephant",
|
||||
);
|
||||
assert.equal(narrow_title.compute_narrow_title(filter), "translated: Unknown channel");
|
||||
|
||||
// Direct messages with narrows
|
||||
const joe = {
|
||||
|
|
|
@ -171,7 +171,7 @@ run_test("basics", ({override, override_rewire}) => {
|
|||
override_rewire(message_view, "try_rendering_locally_for_same_narrow", noop);
|
||||
|
||||
const helper = test_helper({override});
|
||||
const terms = [{operator: "stream", operand: "Denmark"}];
|
||||
const terms = [{operator: "stream", operand: denmark.stream_id.toString()}];
|
||||
|
||||
const selected_id = 1000;
|
||||
|
||||
|
|
|
@ -40,26 +40,27 @@ test("stream", () => {
|
|||
assert.ok(!narrow_state.filter());
|
||||
assert.equal(narrow_state.stream_id(), undefined);
|
||||
|
||||
const test_stream = {name: "Test", stream_id: 15};
|
||||
const test_stream_id = 15;
|
||||
const test_stream = {name: "Test", stream_id: test_stream_id};
|
||||
stream_data.add_sub(test_stream);
|
||||
|
||||
assert.ok(!narrow_state.is_for_stream_id(test_stream.stream_id));
|
||||
|
||||
set_filter([
|
||||
["stream", "Test"],
|
||||
["stream", test_stream_id.toString()],
|
||||
["topic", "Bar"],
|
||||
["search", "yo"],
|
||||
]);
|
||||
assert.ok(narrow_state.filter());
|
||||
|
||||
assert.equal(narrow_state.stream_name(), "Test");
|
||||
assert.equal(narrow_state.stream_id(), 15);
|
||||
assert.equal(narrow_state.stream_id(), test_stream_id);
|
||||
assert.equal(narrow_state.stream_sub().stream_id, test_stream.stream_id);
|
||||
assert.equal(narrow_state.topic(), "Bar");
|
||||
assert.ok(narrow_state.is_for_stream_id(test_stream.stream_id));
|
||||
|
||||
const expected_terms = [
|
||||
{negated: false, operator: "channel", operand: "Test"},
|
||||
{negated: false, operator: "channel", operand: test_stream_id.toString()},
|
||||
{negated: false, operator: "topic", operand: "Bar"},
|
||||
{negated: false, operator: "search", operand: "yo"},
|
||||
];
|
||||
|
@ -68,6 +69,8 @@ test("stream", () => {
|
|||
assert.deepEqual(public_terms, expected_terms);
|
||||
});
|
||||
|
||||
const foo_stream_id = 72;
|
||||
const foo_stream = {name: "Foo", stream_id: foo_stream_id};
|
||||
test("narrowed", () => {
|
||||
assert.ok(!narrow_state.narrowed_to_pms());
|
||||
assert.ok(!narrow_state.narrowed_by_reply());
|
||||
|
@ -76,6 +79,8 @@ test("narrowed", () => {
|
|||
assert.ok(!narrow_state.narrowed_by_stream_reply());
|
||||
assert.equal(narrow_state.stream_sub(), undefined);
|
||||
|
||||
stream_data.add_sub(foo_stream);
|
||||
|
||||
set_filter([["stream", "Foo"]]);
|
||||
assert.ok(!narrow_state.narrowed_to_pms());
|
||||
assert.ok(!narrow_state.narrowed_by_reply());
|
||||
|
@ -91,7 +96,7 @@ test("narrowed", () => {
|
|||
assert.ok(!narrow_state.narrowed_by_stream_reply());
|
||||
|
||||
set_filter([
|
||||
["stream", "Foo"],
|
||||
["stream", foo_stream_id.toString()],
|
||||
["topic", "bar"],
|
||||
]);
|
||||
assert.ok(!narrow_state.narrowed_to_pms());
|
||||
|
@ -117,14 +122,14 @@ test("narrowed", () => {
|
|||
|
||||
test("terms", () => {
|
||||
set_filter([
|
||||
["stream", "Foo"],
|
||||
["stream", foo_stream_id.toString()],
|
||||
["topic", "Bar"],
|
||||
["search", "Yo"],
|
||||
]);
|
||||
let result = narrow_state.search_terms();
|
||||
assert.equal(result.length, 3);
|
||||
assert.equal(result[0].operator, "channel");
|
||||
assert.equal(result[0].operand, "Foo");
|
||||
assert.equal(result[0].operand, foo_stream_id.toString());
|
||||
|
||||
assert.equal(result[1].operator, "topic");
|
||||
assert.equal(result[1].operand, "Bar");
|
||||
|
@ -136,11 +141,11 @@ test("terms", () => {
|
|||
result = narrow_state.search_terms();
|
||||
assert.equal(result.length, 0);
|
||||
|
||||
page_params.narrow = [{operator: "stream", operand: "Foo"}];
|
||||
page_params.narrow = [{operator: "stream", operand: foo_stream_id.toString()}];
|
||||
result = narrow_state.search_terms();
|
||||
assert.equal(result.length, 1);
|
||||
assert.equal(result[0].operator, "channel");
|
||||
assert.equal(result[0].operand, "Foo");
|
||||
assert.equal(result[0].operand, foo_stream_id.toString());
|
||||
});
|
||||
|
||||
test("excludes_muted_topics", () => {
|
||||
|
@ -169,7 +174,7 @@ test("excludes_muted_topics", () => {
|
|||
|
||||
test("set_compose_defaults", () => {
|
||||
set_filter([
|
||||
["stream", "Foo"],
|
||||
["stream", foo_stream_id.toString()],
|
||||
["topic", "Bar"],
|
||||
]);
|
||||
|
||||
|
@ -178,10 +183,9 @@ test("set_compose_defaults", () => {
|
|||
assert.equal(stream_and_topic.stream_id, undefined);
|
||||
assert.equal(stream_and_topic.topic, "Bar");
|
||||
|
||||
const test_stream = {name: "Foo", stream_id: 72};
|
||||
stream_data.add_sub(test_stream);
|
||||
stream_data.add_sub(foo_stream);
|
||||
stream_and_topic = narrow_state.set_compose_defaults();
|
||||
assert.equal(stream_and_topic.stream_id, 72);
|
||||
assert.equal(stream_and_topic.stream_id, foo_stream_id);
|
||||
assert.equal(stream_and_topic.topic, "Bar");
|
||||
|
||||
set_filter([["dm", "foo@bar.com"]]);
|
||||
|
@ -212,11 +216,12 @@ test("set_compose_defaults", () => {
|
|||
]);
|
||||
assert.deepEqual(narrow_state.set_compose_defaults(), {});
|
||||
|
||||
stream_data.add_sub({name: "ROME", stream_id: 99});
|
||||
set_filter([["stream", "rome"]]);
|
||||
const rome_id = 99;
|
||||
stream_data.add_sub({name: "ROME", stream_id: rome_id});
|
||||
set_filter([["stream", rome_id.toString()]]);
|
||||
|
||||
const stream_test = narrow_state.set_compose_defaults();
|
||||
assert.equal(stream_test.stream_id, 99);
|
||||
assert.equal(stream_test.stream_id, rome_id);
|
||||
});
|
||||
|
||||
test("update_email", () => {
|
||||
|
@ -241,7 +246,7 @@ test("update_email", () => {
|
|||
|
||||
test("topic", () => {
|
||||
set_filter([
|
||||
["stream", "Foo"],
|
||||
["stream", foo_stream.stream_id.toString()],
|
||||
["topic", "Bar"],
|
||||
]);
|
||||
assert.equal(narrow_state.topic(), "Bar");
|
||||
|
@ -271,14 +276,15 @@ test("stream_sub", () => {
|
|||
assert.equal(narrow_state.stream_sub(), undefined);
|
||||
|
||||
set_filter([
|
||||
["stream", "Foo"],
|
||||
["stream", "55"],
|
||||
["topic", "Bar"],
|
||||
]);
|
||||
assert.equal(narrow_state.stream_name(), "Foo");
|
||||
assert.equal(narrow_state.stream_name(), undefined);
|
||||
assert.equal(narrow_state.stream_sub(), undefined);
|
||||
|
||||
const sub = {name: "Foo", stream_id: 55};
|
||||
stream_data.add_sub(sub);
|
||||
assert.equal(narrow_state.stream_name(), "Foo");
|
||||
assert.deepEqual(narrow_state.stream_sub(), sub);
|
||||
|
||||
set_filter([
|
||||
|
@ -297,7 +303,7 @@ test("pm_ids_string", () => {
|
|||
assert.deepStrictEqual(narrow_state.pm_ids_set(), new Set());
|
||||
|
||||
set_filter([
|
||||
["stream", "Foo"],
|
||||
["stream", foo_stream.stream_id.toString()],
|
||||
["topic", "Bar"],
|
||||
]);
|
||||
assert.equal(narrow_state.pm_ids_string(), undefined);
|
||||
|
|
|
@ -25,6 +25,8 @@ const alice = {
|
|||
full_name: "Alice",
|
||||
};
|
||||
|
||||
const bogus_stream_id = "999999";
|
||||
|
||||
people.init();
|
||||
people.add_active_user(alice);
|
||||
|
||||
|
@ -111,12 +113,12 @@ run_test("get_unread_ids", () => {
|
|||
assert.deepEqual(unread_ids, []);
|
||||
assert_unread_info({flavor: "not_found"});
|
||||
|
||||
terms = [{operator: "stream", operand: "bogus"}];
|
||||
terms = [{operator: "stream", operand: bogus_stream_id}];
|
||||
set_filter(terms);
|
||||
unread_ids = candidate_ids();
|
||||
assert.deepEqual(unread_ids, []);
|
||||
|
||||
terms = [{operator: "stream", operand: sub.name}];
|
||||
terms = [{operator: "stream", operand: sub.stream_id.toString()}];
|
||||
set_filter(terms);
|
||||
unread_ids = candidate_ids();
|
||||
assert.deepEqual(unread_ids, []);
|
||||
|
@ -131,7 +133,7 @@ run_test("get_unread_ids", () => {
|
|||
});
|
||||
|
||||
terms = [
|
||||
{operator: "stream", operand: "bogus"},
|
||||
{operator: "stream", operand: bogus_stream_id},
|
||||
{operator: "topic", operand: "my topic"},
|
||||
];
|
||||
set_filter(terms);
|
||||
|
@ -139,7 +141,7 @@ run_test("get_unread_ids", () => {
|
|||
assert.deepEqual(unread_ids, []);
|
||||
|
||||
terms = [
|
||||
{operator: "stream", operand: sub.name},
|
||||
{operator: "stream", operand: sub.stream_id.toString()},
|
||||
{operator: "topic", operand: "my topic"},
|
||||
];
|
||||
set_filter(terms);
|
||||
|
@ -226,7 +228,7 @@ run_test("get_unread_ids", () => {
|
|||
// destination topic.
|
||||
unread.process_loaded_messages([other_topic_message]);
|
||||
terms = [
|
||||
{operator: "channel", operand: sub.name},
|
||||
{operator: "channel", operand: sub.stream_id.toString()},
|
||||
{operator: "topic", operand: "another topic"},
|
||||
];
|
||||
set_filter(terms);
|
||||
|
@ -234,7 +236,7 @@ run_test("get_unread_ids", () => {
|
|||
assert.deepEqual(unread_ids, [other_topic_message.id]);
|
||||
|
||||
terms = [
|
||||
{operator: "channel", operand: sub.name},
|
||||
{operator: "channel", operand: sub.stream_id.toString()},
|
||||
{operator: "topic", operand: "another topic"},
|
||||
{operator: "with", operand: stream_msg.id},
|
||||
];
|
||||
|
@ -243,7 +245,7 @@ run_test("get_unread_ids", () => {
|
|||
assert.deepEqual(unread_ids, [stream_msg.id]);
|
||||
|
||||
terms = [
|
||||
{operator: "channel", operand: sub.name},
|
||||
{operator: "channel", operand: sub.stream_id.toString()},
|
||||
{operator: "topic", operand: "another topic"},
|
||||
{operator: "with", operand: private_msg.id},
|
||||
];
|
||||
|
|
|
@ -66,19 +66,19 @@ test("unsubscribe", () => {
|
|||
stream_data.add_sub(devel);
|
||||
|
||||
// verify clean slate
|
||||
assert.ok(!stream_data.is_subscribed_by_name("devel"));
|
||||
assert.ok(!stream_data.is_subscribed(devel.stream_id));
|
||||
|
||||
// set up our subscription
|
||||
devel.subscribed = true;
|
||||
peer_data.set_subscribers(devel.stream_id, [me.user_id]);
|
||||
|
||||
// ensure our setup is accurate
|
||||
assert.ok(stream_data.is_subscribed_by_name("devel"));
|
||||
assert.ok(stream_data.is_subscribed(devel.stream_id));
|
||||
|
||||
// DO THE UNSUBSCRIBE HERE
|
||||
stream_data.unsubscribe_myself(devel);
|
||||
assert.ok(!devel.subscribed);
|
||||
assert.ok(!stream_data.is_subscribed_by_name("devel"));
|
||||
assert.ok(!stream_data.is_subscribed(devel.stream_id));
|
||||
assert.ok(!contains_sub(stream_data.subscribed_subs(), devel));
|
||||
assert.ok(contains_sub(stream_data.unsubscribed_subs(), devel));
|
||||
|
||||
|
@ -96,7 +96,7 @@ test("subscribers", () => {
|
|||
people.add_active_user(george);
|
||||
|
||||
// verify setup
|
||||
assert.ok(stream_data.is_subscribed_by_name(sub.name));
|
||||
assert.ok(stream_data.is_subscribed(sub.stream_id));
|
||||
|
||||
const stream_id = sub.stream_id;
|
||||
|
||||
|
|
|
@ -237,25 +237,26 @@ run_test("initialize", ({override, override_rewire, mock_template}) => {
|
|||
assert.equal(opts.updater("ver"), "ver");
|
||||
assert.ok(!input_pill_displayed);
|
||||
|
||||
const verona_stream_id = verona.stream_id.toString();
|
||||
terms = [
|
||||
{
|
||||
negated: false,
|
||||
operator: "channel",
|
||||
operand: "Verona",
|
||||
operand: verona_stream_id,
|
||||
},
|
||||
];
|
||||
expected_pill_display_value = "channel: Verona";
|
||||
_setup(terms);
|
||||
input_pill_displayed = false;
|
||||
mock_pill_removes(search.search_pill_widget);
|
||||
assert.equal(opts.updater("channel:Verona"), "");
|
||||
assert.equal(opts.updater(`channel:${verona_stream_id}`), "");
|
||||
assert.ok(input_pill_displayed);
|
||||
|
||||
search.__Rewire__("is_using_input_method", true);
|
||||
_setup(terms);
|
||||
input_pill_displayed = false;
|
||||
mock_pill_removes(search.search_pill_widget);
|
||||
assert.equal(opts.updater("channel:Verona"), "");
|
||||
assert.equal(opts.updater(`channel:${verona_stream_id}`), "");
|
||||
assert.ok(input_pill_displayed);
|
||||
}
|
||||
return {
|
||||
|
|
|
@ -50,6 +50,12 @@ const jeff = {
|
|||
|
||||
const example_avatar_url = "http://example.com/example.png";
|
||||
|
||||
let _stream_id = 0;
|
||||
function new_stream_id() {
|
||||
_stream_id += 1;
|
||||
return _stream_id;
|
||||
}
|
||||
|
||||
function init() {
|
||||
current_user.is_admin = true;
|
||||
|
||||
|
@ -81,7 +87,7 @@ function test(label, f) {
|
|||
test("basic_get_suggestions", ({override}) => {
|
||||
const query = "fred";
|
||||
|
||||
override(narrow_state, "stream_name", () => "office");
|
||||
override(narrow_state, "stream_id", noop);
|
||||
|
||||
const suggestions = get_suggestions(query);
|
||||
|
||||
|
@ -116,14 +122,17 @@ test("get_is_suggestions_for_spectator", () => {
|
|||
test("subset_suggestions", ({mock_template}) => {
|
||||
mock_template("search_description.hbs", true, (_data, html) => html);
|
||||
|
||||
const query = "channel:Denmark topic:Hamlet shakespeare";
|
||||
const denmark_id = new_stream_id();
|
||||
const sub = {name: "Denmark", stream_id: denmark_id};
|
||||
stream_data.add_sub(sub);
|
||||
const query = `channel:${denmark_id} topic:Hamlet shakespeare`;
|
||||
|
||||
const suggestions = get_suggestions(query);
|
||||
|
||||
const expected = [
|
||||
"channel:Denmark topic:Hamlet shakespeare",
|
||||
"channel:Denmark topic:Hamlet",
|
||||
"channel:Denmark",
|
||||
`channel:${denmark_id} topic:Hamlet shakespeare`,
|
||||
`channel:${denmark_id} topic:Hamlet`,
|
||||
`channel:${denmark_id}`,
|
||||
];
|
||||
|
||||
assert.deepEqual(suggestions.strings, expected);
|
||||
|
@ -249,7 +258,7 @@ test("dm_suggestions", ({override, mock_template}) => {
|
|||
|
||||
// "pm-with" operator returns search result
|
||||
// and "dm" operator as a suggestions
|
||||
override(narrow_state, "stream_name", () => undefined);
|
||||
override(narrow_state, "stream_id", () => undefined);
|
||||
query = "pm-with";
|
||||
suggestions = get_suggestions(query);
|
||||
expected = ["pm-with", "dm:"];
|
||||
|
@ -330,10 +339,10 @@ test("group_suggestions", ({mock_template}) => {
|
|||
assert.deepEqual(suggestions.strings, expected);
|
||||
|
||||
// Doesn't show dms because it's invalid in combination
|
||||
// with a channel.
|
||||
query = "channel:Denmark has:link dm:bob@zulip.com,Smit";
|
||||
// with a channel. (Random channel id.)
|
||||
query = "channel:66 has:link dm:bob@zulip.com,Smit";
|
||||
suggestions = get_suggestions(query);
|
||||
expected = ["channel:Denmark has:link", "channel:Denmark"];
|
||||
expected = ["channel:66 has:link", "channel:66"];
|
||||
assert.deepEqual(suggestions.strings, expected);
|
||||
|
||||
// Invalid emails don't give suggestions
|
||||
|
@ -346,8 +355,10 @@ test("group_suggestions", ({mock_template}) => {
|
|||
test("empty_query_suggestions", () => {
|
||||
const query = "";
|
||||
|
||||
stream_data.add_sub({stream_id: 44, name: "devel", subscribed: true});
|
||||
stream_data.add_sub({stream_id: 77, name: "office", subscribed: true});
|
||||
const devel_id = new_stream_id();
|
||||
const office_id = new_stream_id();
|
||||
stream_data.add_sub({stream_id: devel_id, name: "devel", subscribed: true});
|
||||
stream_data.add_sub({stream_id: office_id, name: "office", subscribed: true});
|
||||
|
||||
const suggestions = get_suggestions(query);
|
||||
|
||||
|
@ -361,8 +372,8 @@ test("empty_query_suggestions", () => {
|
|||
"is:unread",
|
||||
"is:resolved",
|
||||
"sender:myself@zulip.com",
|
||||
"channel:devel",
|
||||
"channel:office",
|
||||
`channel:${devel_id}`,
|
||||
`channel:${office_id}`,
|
||||
"has:link",
|
||||
"has:image",
|
||||
"has:attachment",
|
||||
|
@ -395,7 +406,7 @@ test("has_suggestions", ({override, mock_template}) => {
|
|||
let query = "h";
|
||||
stream_data.add_sub({stream_id: 44, name: "devel", subscribed: true});
|
||||
stream_data.add_sub({stream_id: 77, name: "office", subscribed: true});
|
||||
override(narrow_state, "stream_name", noop);
|
||||
override(narrow_state, "stream_id", noop);
|
||||
|
||||
let suggestions = get_suggestions(query);
|
||||
let expected = ["h", "has:link", "has:image", "has:attachment", "has:reaction"];
|
||||
|
@ -439,13 +450,10 @@ test("has_suggestions", ({override, mock_template}) => {
|
|||
expected = ["att", "has:attachment"];
|
||||
assert.deepEqual(suggestions.strings, expected);
|
||||
|
||||
query = "channel:Denmark is:alerted has:lin";
|
||||
// 66 is misc channel id.
|
||||
query = "channel:66 is:alerted has:lin";
|
||||
suggestions = get_suggestions(query);
|
||||
expected = [
|
||||
"channel:Denmark is:alerted has:link",
|
||||
"channel:Denmark is:alerted",
|
||||
"channel:Denmark",
|
||||
];
|
||||
expected = ["channel:66 is:alerted has:link", "channel:66 is:alerted", "channel:66"];
|
||||
assert.deepEqual(suggestions.strings, expected);
|
||||
});
|
||||
|
||||
|
@ -453,9 +461,7 @@ test("check_is_suggestions", ({override, mock_template}) => {
|
|||
mock_template("search_description.hbs", true, (_data, html) => html);
|
||||
mock_template("user_pill.hbs", true, (_data, html) => html);
|
||||
|
||||
stream_data.add_sub({stream_id: 44, name: "devel", subscribed: true});
|
||||
stream_data.add_sub({stream_id: 77, name: "office", subscribed: true});
|
||||
override(narrow_state, "stream_name", noop);
|
||||
override(narrow_state, "stream_id", noop);
|
||||
|
||||
let query = "i";
|
||||
let suggestions = get_suggestions(query);
|
||||
|
@ -541,20 +547,16 @@ test("check_is_suggestions", ({override, mock_template}) => {
|
|||
expected = ["st", "streams:public", "is:starred", "channel:"];
|
||||
assert.deepEqual(suggestions.strings, expected);
|
||||
|
||||
query = "channel:Denmark has:link is:sta";
|
||||
query = "channel:66 has:link is:sta";
|
||||
suggestions = get_suggestions(query);
|
||||
expected = [
|
||||
"channel:Denmark has:link is:starred",
|
||||
"channel:Denmark has:link",
|
||||
"channel:Denmark",
|
||||
];
|
||||
expected = ["channel:66 has:link is:starred", "channel:66 has:link", "channel:66"];
|
||||
assert.deepEqual(suggestions.strings, expected);
|
||||
});
|
||||
|
||||
test("sent_by_me_suggestions", ({override, mock_template}) => {
|
||||
mock_template("search_description.hbs", true, (_data, html) => html);
|
||||
|
||||
override(narrow_state, "stream_name", noop);
|
||||
override(narrow_state, "stream_id", noop);
|
||||
|
||||
let query = "";
|
||||
let suggestions = get_suggestions(query);
|
||||
|
@ -604,13 +606,16 @@ test("sent_by_me_suggestions", ({override, mock_template}) => {
|
|||
expected = ["-sent", "-sender:myself@zulip.com"];
|
||||
assert.deepEqual(suggestions.strings, expected);
|
||||
|
||||
query = "channel:Denmark topic:Denmark1 sent";
|
||||
const denmark_id = new_stream_id();
|
||||
const sub = {name: "Denmark", stream_id: denmark_id};
|
||||
stream_data.add_sub(sub);
|
||||
query = `channel:${denmark_id} topic:Denmark1 sent`;
|
||||
suggestions = get_suggestions(query);
|
||||
expected = [
|
||||
"channel:Denmark topic:Denmark1 sent",
|
||||
"channel:Denmark topic:Denmark1 sender:myself@zulip.com",
|
||||
"channel:Denmark topic:Denmark1",
|
||||
"channel:Denmark",
|
||||
`channel:${denmark_id} topic:Denmark1 sent`,
|
||||
`channel:${denmark_id} topic:Denmark1 sender:myself@zulip.com`,
|
||||
`channel:${denmark_id} topic:Denmark1`,
|
||||
`channel:${denmark_id}`,
|
||||
];
|
||||
assert.deepEqual(suggestions.strings, expected);
|
||||
|
||||
|
@ -627,11 +632,11 @@ test("topic_suggestions", ({override, mock_template}) => {
|
|||
let expected;
|
||||
|
||||
override(stream_topic_history_util, "get_server_history", noop);
|
||||
stream_data.add_sub({stream_id: 77, name: "office", subscribed: true});
|
||||
override(narrow_state, "stream_name", () => "office");
|
||||
const office_id = new_stream_id();
|
||||
stream_data.add_sub({stream_id: office_id, name: "office", subscribed: true});
|
||||
override(narrow_state, "stream_id", () => office_id);
|
||||
|
||||
const devel_id = 44;
|
||||
const office_id = 77;
|
||||
const devel_id = new_stream_id();
|
||||
stream_data.add_sub({stream_id: devel_id, name: "devel", subscribed: true});
|
||||
stream_data.add_sub({stream_id: office_id, name: "office", subscribed: true});
|
||||
|
||||
|
@ -657,8 +662,8 @@ test("topic_suggestions", ({override, mock_template}) => {
|
|||
"dm:ted@zulip.com",
|
||||
"sender:ted@zulip.com",
|
||||
"dm-including:ted@zulip.com",
|
||||
"channel:office topic:team",
|
||||
"channel:office topic:test",
|
||||
`channel:${office_id} topic:team`,
|
||||
`channel:${office_id} topic:test`,
|
||||
];
|
||||
assert.deepEqual(suggestions.strings, expected);
|
||||
|
||||
|
@ -666,40 +671,56 @@ test("topic_suggestions", ({override, mock_template}) => {
|
|||
return suggestions.lookup_table.get(q).description_html;
|
||||
}
|
||||
assert.equal(describe("te"), "Search for <strong>te</strong>");
|
||||
assert.equal(describe("channel:office topic:team"), "Channel office > team");
|
||||
assert.equal(describe(`channel:${office_id} topic:team`), "Channel office > team");
|
||||
|
||||
suggestions = get_suggestions("topic:staplers channel:office");
|
||||
expected = ["topic:staplers channel:office", "topic:staplers"];
|
||||
suggestions = get_suggestions(`topic:staplers channel:${office_id}`);
|
||||
expected = [`topic:staplers channel:${office_id}`, "topic:staplers"];
|
||||
assert.deepEqual(suggestions.strings, expected);
|
||||
|
||||
suggestions = get_suggestions("channel:devel topic:");
|
||||
expected = ["channel:devel topic:", "channel:devel topic:REXX", "channel:devel"];
|
||||
suggestions = get_suggestions(`channel:${devel_id} topic:`);
|
||||
expected = [
|
||||
`channel:${devel_id} topic:`,
|
||||
`channel:${devel_id} topic:REXX`,
|
||||
`channel:${devel_id}`,
|
||||
];
|
||||
assert.deepEqual(suggestions.strings, expected);
|
||||
|
||||
suggestions = get_suggestions("channel:devel -topic:");
|
||||
expected = ["channel:devel -topic:", "channel:devel -topic:REXX", "channel:devel"];
|
||||
suggestions = get_suggestions(`channel:${devel_id} -topic:`);
|
||||
expected = [
|
||||
`channel:${devel_id} -topic:`,
|
||||
`channel:${devel_id} -topic:REXX`,
|
||||
`channel:${devel_id}`,
|
||||
];
|
||||
assert.deepEqual(suggestions.strings, expected);
|
||||
|
||||
suggestions = get_suggestions("-topic:te");
|
||||
expected = ["-topic:te", "channel:office -topic:team", "channel:office -topic:test"];
|
||||
expected = [
|
||||
"-topic:te",
|
||||
`channel:${office_id} -topic:team`,
|
||||
`channel:${office_id} -topic:test`,
|
||||
];
|
||||
assert.deepEqual(suggestions.strings, expected);
|
||||
|
||||
suggestions = get_suggestions("is:alerted channel:devel is:starred topic:");
|
||||
suggestions = get_suggestions(`is:alerted channel:${devel_id} is:starred topic:`);
|
||||
expected = [
|
||||
"is:alerted channel:devel is:starred topic:",
|
||||
"is:alerted channel:devel is:starred topic:REXX",
|
||||
"is:alerted channel:devel is:starred",
|
||||
"is:alerted channel:devel",
|
||||
`is:alerted channel:${devel_id} is:starred topic:`,
|
||||
`is:alerted channel:${devel_id} is:starred topic:REXX`,
|
||||
`is:alerted channel:${devel_id} is:starred`,
|
||||
`is:alerted channel:${devel_id}`,
|
||||
"is:alerted",
|
||||
];
|
||||
assert.deepEqual(suggestions.strings, expected);
|
||||
|
||||
suggestions = get_suggestions("is:dm channel:devel topic:");
|
||||
expected = ["is:dm channel:devel topic:", "is:dm channel:devel", "is:dm"];
|
||||
suggestions = get_suggestions(`is:dm channel:${devel_id} topic:`);
|
||||
expected = [`is:dm channel:${devel_id} topic:`, `is:dm channel:${devel_id}`, `is:dm`];
|
||||
assert.deepEqual(suggestions.strings, expected);
|
||||
|
||||
suggestions = get_suggestions("topic:REXX channel:devel topic:");
|
||||
expected = ["topic:REXX channel:devel topic:", "topic:REXX channel:devel", "topic:REXX"];
|
||||
suggestions = get_suggestions(`topic:REXX channel:${devel_id} topic:`);
|
||||
expected = [
|
||||
`topic:REXX channel:${devel_id} topic:`,
|
||||
`topic:REXX channel:${devel_id}`,
|
||||
"topic:REXX",
|
||||
];
|
||||
assert.deepEqual(suggestions.strings, expected);
|
||||
});
|
||||
|
||||
|
@ -748,38 +769,41 @@ test("topic_suggestions (limits)", () => {
|
|||
|
||||
test("whitespace_glitch", ({override, mock_template}) => {
|
||||
mock_template("search_description.hbs", true, (_data, html) => html);
|
||||
const office_stream_id = new_stream_id();
|
||||
|
||||
const query = "channel:office "; // note trailing space
|
||||
|
||||
override(stream_topic_history_util, "get_server_history", noop);
|
||||
stream_data.add_sub({stream_id: 77, name: "office", subscribed: true});
|
||||
stream_data.add_sub({stream_id: office_stream_id, name: "office", subscribed: true});
|
||||
|
||||
const suggestions = get_suggestions(query);
|
||||
|
||||
const expected = ["channel:office"];
|
||||
const expected = [`channel:${office_stream_id}`];
|
||||
|
||||
assert.deepEqual(suggestions.strings, expected);
|
||||
});
|
||||
|
||||
test("channel_completion", ({override}) => {
|
||||
stream_data.add_sub({stream_id: 77, name: "office", subscribed: true});
|
||||
stream_data.add_sub({stream_id: 88, name: "dev help", subscribed: true});
|
||||
const office_stream_id = new_stream_id();
|
||||
stream_data.add_sub({stream_id: office_stream_id, name: "office", subscribed: true});
|
||||
const dev_help_stream_id = new_stream_id();
|
||||
stream_data.add_sub({stream_id: dev_help_stream_id, name: "dev help", subscribed: true});
|
||||
|
||||
override(narrow_state, "stream_name", noop);
|
||||
override(narrow_state, "stream_id", noop);
|
||||
|
||||
let query = "channel:of";
|
||||
let suggestions = get_suggestions(query);
|
||||
let expected = ["channel:office"];
|
||||
let expected = [`channel:${office_stream_id}`];
|
||||
assert.deepEqual(suggestions.strings, expected);
|
||||
|
||||
query = "-channel:of";
|
||||
suggestions = get_suggestions(query);
|
||||
expected = ["-channel:office"];
|
||||
expected = [`-channel:${office_stream_id}`];
|
||||
assert.deepEqual(suggestions.strings, expected);
|
||||
|
||||
query = "hel";
|
||||
suggestions = get_suggestions(query);
|
||||
expected = ["hel", "channel:dev+help"];
|
||||
expected = ["hel", `channel:${dev_help_stream_id}`];
|
||||
assert.deepEqual(suggestions.strings, expected);
|
||||
});
|
||||
|
||||
|
@ -789,7 +813,7 @@ test("people_suggestions", ({override, mock_template}) => {
|
|||
|
||||
let query = "te";
|
||||
|
||||
override(narrow_state, "stream_name", noop);
|
||||
override(narrow_state, "stream_id", noop);
|
||||
|
||||
const ted = {
|
||||
email: "ted@zulip.com",
|
||||
|
@ -959,7 +983,7 @@ test("people_suggestions", ({override, mock_template}) => {
|
|||
test("operator_suggestions", ({override, mock_template}) => {
|
||||
mock_template("search_description.hbs", true, (_data, html) => html);
|
||||
|
||||
override(narrow_state, "stream_name", () => undefined);
|
||||
override(narrow_state, "stream_id", () => undefined);
|
||||
|
||||
// Completed operator should return nothing
|
||||
let query = "channel:";
|
||||
|
@ -977,37 +1001,40 @@ test("operator_suggestions", ({override, mock_template}) => {
|
|||
expected = ["-s", "-sender:myself@zulip.com", "-sender:", "-channel:"];
|
||||
assert.deepEqual(suggestions.strings, expected);
|
||||
|
||||
query = "channel:Denmark is:alerted -f";
|
||||
// 66 is a misc channel id.
|
||||
query = "channel:66 is:alerted -f";
|
||||
suggestions = get_suggestions(query);
|
||||
expected = [
|
||||
"channel:Denmark is:alerted -f",
|
||||
"channel:Denmark is:alerted -sender:myself@zulip.com",
|
||||
"channel:Denmark is:alerted -sender:",
|
||||
"channel:Denmark is:alerted",
|
||||
"channel:Denmark",
|
||||
"channel:66 is:alerted -f",
|
||||
"channel:66 is:alerted -sender:myself@zulip.com",
|
||||
"channel:66 is:alerted -sender:",
|
||||
"channel:66 is:alerted",
|
||||
"channel:66",
|
||||
];
|
||||
assert.deepEqual(suggestions.strings, expected);
|
||||
});
|
||||
|
||||
test("queries_with_spaces", () => {
|
||||
stream_data.add_sub({stream_id: 77, name: "office", subscribed: true});
|
||||
stream_data.add_sub({stream_id: 88, name: "dev help", subscribed: true});
|
||||
const office_id = new_stream_id();
|
||||
stream_data.add_sub({stream_id: office_id, name: "office", subscribed: true});
|
||||
const dev_help_id = new_stream_id();
|
||||
stream_data.add_sub({stream_id: dev_help_id, name: "dev help", subscribed: true});
|
||||
|
||||
// test allowing spaces with quotes surrounding operand
|
||||
let query = 'channel:"dev he"';
|
||||
let suggestions = get_suggestions(query);
|
||||
let expected = ["channel:dev+help"];
|
||||
let expected = [`channel:${dev_help_id}`];
|
||||
assert.deepEqual(suggestions.strings, expected);
|
||||
|
||||
// test mismatched quote
|
||||
query = 'channel:"dev h';
|
||||
suggestions = get_suggestions(query);
|
||||
expected = ["channel:dev+help"];
|
||||
expected = [`channel:${dev_help_id}`];
|
||||
assert.deepEqual(suggestions.strings, expected);
|
||||
|
||||
// test extra space after operator still works
|
||||
query = "channel: offi";
|
||||
suggestions = get_suggestions(query);
|
||||
expected = ["channel:office"];
|
||||
expected = [`channel:${office_id}`];
|
||||
assert.deepEqual(suggestions.strings, expected);
|
||||
});
|
||||
|
|
|
@ -17,6 +17,7 @@ const people = zrequire("people");
|
|||
const settings_config = zrequire("settings_config");
|
||||
const sub_store = zrequire("sub_store");
|
||||
const stream_data = zrequire("stream_data");
|
||||
const hash_util = zrequire("hash_util");
|
||||
const stream_settings_data = zrequire("stream_settings_data");
|
||||
const user_groups = zrequire("user_groups");
|
||||
|
||||
|
@ -135,10 +136,8 @@ test("basics", () => {
|
|||
assert.deepEqual(stream_data.get_colors(), ["red", "yellow"]);
|
||||
assert.deepEqual(stream_data.subscribed_stream_ids(), [social.stream_id, test.stream_id]);
|
||||
|
||||
assert.ok(stream_data.is_subscribed_by_name("social"));
|
||||
assert.ok(stream_data.is_subscribed_by_name("Social"));
|
||||
assert.ok(!stream_data.is_subscribed_by_name("Denmark"));
|
||||
assert.ok(!stream_data.is_subscribed_by_name("Rome"));
|
||||
assert.ok(stream_data.is_subscribed(social.stream_id));
|
||||
assert.ok(!stream_data.is_subscribed(denmark.stream_id));
|
||||
|
||||
assert.equal(stream_data.get_stream_privacy_policy(test.stream_id), "public");
|
||||
assert.equal(stream_data.get_stream_privacy_policy(social.stream_id), "invite-only");
|
||||
|
@ -147,9 +146,10 @@ test("basics", () => {
|
|||
"invite-only-public-history",
|
||||
);
|
||||
assert.equal(stream_data.get_stream_privacy_policy(web_public_stream.stream_id), "web-public");
|
||||
assert.ok(stream_data.is_web_public_by_stream_name(web_public_stream.name));
|
||||
assert.ok(!stream_data.is_web_public_by_stream_name(social.name));
|
||||
assert.ok(!stream_data.is_web_public_by_stream_name("unknown"));
|
||||
assert.ok(stream_data.is_web_public_by_stream_id(web_public_stream.stream_id));
|
||||
assert.ok(!stream_data.is_web_public_by_stream_id(social.stream_id));
|
||||
const unknown_stream_id = 9999;
|
||||
assert.ok(!stream_data.is_web_public_by_stream_id(unknown_stream_id));
|
||||
|
||||
assert.ok(stream_data.is_invite_only_by_stream_id(social.stream_id));
|
||||
// Unknown stream id
|
||||
|
@ -159,9 +159,6 @@ test("basics", () => {
|
|||
assert.equal(stream_data.get_color(undefined), "#c2c2c2");
|
||||
assert.equal(stream_data.get_color(1234567), "#c2c2c2");
|
||||
|
||||
assert.equal(stream_data.get_name("denMARK"), "Denmark");
|
||||
assert.equal(stream_data.get_name("unknown Stream"), "unknown Stream");
|
||||
|
||||
assert.ok(!stream_data.is_muted(social.stream_id));
|
||||
assert.ok(stream_data.is_muted(denmark.stream_id));
|
||||
|
||||
|
@ -176,19 +173,37 @@ test("basics", () => {
|
|||
|
||||
// "new" correct url formats
|
||||
assert.equal(stream_data.slug_to_stream_id("2-social"), 2);
|
||||
assert.equal(hash_util.decode_operand("channel", "2-social"), "2");
|
||||
|
||||
assert.equal(stream_data.slug_to_stream_id("2"), 2);
|
||||
assert.equal(hash_util.decode_operand("channel", "2"), "2");
|
||||
|
||||
// we still get 2 because it's a valid stream id
|
||||
assert.equal(stream_data.slug_to_stream_id("2-whatever"), 2);
|
||||
// invalid stream id
|
||||
assert.equal(stream_data.slug_to_stream_id("999-social"), undefined);
|
||||
// legacy
|
||||
assert.equal(stream_data.slug_to_stream_id("social"), 2);
|
||||
assert.equal(stream_data.slug_to_stream_id("2-"), 2);
|
||||
|
||||
// legacy, we recognize "social" as a valid channel name
|
||||
assert.equal(stream_data.slug_to_stream_id("social"), 2);
|
||||
assert.equal(hash_util.decode_operand("channel", "social"), "2");
|
||||
|
||||
// These aren't prepended with valid ids nor valid channel names. We
|
||||
// don't get any stream id from the slug, and the decoded operand (the
|
||||
// only caller of `slug_to_stream_id`) returns an empty string (which we
|
||||
// don't display anywhere, since the channel is invalid).
|
||||
assert.equal(stream_data.slug_to_stream_id("999-social"), undefined);
|
||||
assert.equal(hash_util.decode_operand("channel", "999-social"), "");
|
||||
|
||||
// invalid formats
|
||||
assert.equal(stream_data.slug_to_stream_id("25-or-6-to-4"), undefined);
|
||||
assert.equal(stream_data.slug_to_stream_id("2something"), undefined);
|
||||
assert.equal(stream_data.slug_to_stream_id("99-whatever"), undefined);
|
||||
assert.equal(hash_util.decode_operand("channel", "99-whatever"), "");
|
||||
|
||||
assert.equal(stream_data.slug_to_stream_id("25-or-6-to-4"), undefined);
|
||||
assert.equal(hash_util.decode_operand("channel", "25-or-6-to-4"), "");
|
||||
|
||||
assert.equal(stream_data.slug_to_stream_id("2something"), undefined);
|
||||
assert.equal(hash_util.decode_operand("channel", "2something"), "");
|
||||
|
||||
assert.equal(stream_data.slug_to_stream_id("99whatever"), undefined);
|
||||
assert.equal(hash_util.decode_operand("channel", "99whatever"), "");
|
||||
|
||||
// sub_store
|
||||
assert.equal(sub_store.get(-3), undefined);
|
||||
|
@ -528,12 +543,12 @@ test("delete_sub", () => {
|
|||
|
||||
stream_data.add_sub(canada);
|
||||
|
||||
assert.ok(stream_data.is_subscribed_by_name("Canada"));
|
||||
assert.ok(stream_data.is_subscribed(canada.stream_id));
|
||||
assert.equal(stream_data.get_sub("Canada").stream_id, canada.stream_id);
|
||||
assert.equal(sub_store.get(canada.stream_id).name, "Canada");
|
||||
|
||||
stream_data.delete_sub(canada.stream_id);
|
||||
assert.ok(!stream_data.is_subscribed_by_name("Canada"));
|
||||
assert.ok(!stream_data.is_subscribed(canada.stream_id));
|
||||
assert.ok(!stream_data.get_sub("Canada"));
|
||||
assert.ok(!sub_store.get(canada.stream_id));
|
||||
|
||||
|
|
|
@ -83,7 +83,7 @@ const frontend = {
|
|||
};
|
||||
|
||||
function narrow_to_frontend() {
|
||||
const filter = new Filter([{operator: "stream", operand: "frontend"}]);
|
||||
const filter = new Filter([{operator: "stream", operand: frontend.stream_id.toString()}]);
|
||||
message_lists.current = {
|
||||
data: {
|
||||
filter,
|
||||
|
@ -382,12 +382,12 @@ test("marked_subscribed (emails)", ({override}) => {
|
|||
|
||||
$("#channels_overlay_container .stream-row:not(.notdisplayed)").length = 0;
|
||||
|
||||
assert.ok(!stream_data.is_subscribed_by_name(sub.name));
|
||||
assert.ok(!stream_data.is_subscribed(sub.stream_id));
|
||||
|
||||
const user_ids = [15, 20, 25, me.user_id];
|
||||
stream_events.mark_subscribed(sub, user_ids, "");
|
||||
assert.deepEqual(new Set(peer_data.get_subscribers(sub.stream_id)), new Set(user_ids));
|
||||
assert.ok(stream_data.is_subscribed_by_name(sub.name));
|
||||
assert.ok(stream_data.is_subscribed(sub.stream_id));
|
||||
|
||||
const args = subs_stub.get_args("sub");
|
||||
assert.deepEqual(sub, args.sub);
|
||||
|
|
|
@ -429,19 +429,19 @@ test_ui("narrowing", ({mock_template}) => {
|
|||
|
||||
let filter;
|
||||
|
||||
filter = new Filter([{operator: "stream", operand: "devel"}]);
|
||||
filter = new Filter([{operator: "stream", operand: develSub.stream_id.toString()}]);
|
||||
stream_list.handle_narrow_activated(filter);
|
||||
assert.ok($("<devel-sidebar-row-stub>").hasClass("active-filter"));
|
||||
|
||||
filter = new Filter([
|
||||
{operator: "stream", operand: "cars"},
|
||||
{operator: "stream", operand: carSub.stream_id.toString()},
|
||||
{operator: "topic", operand: "sedans"},
|
||||
]);
|
||||
stream_list.handle_narrow_activated(filter);
|
||||
assert.ok(!$("ul.filters li").hasClass("active-filter"));
|
||||
assert.ok(!$("<cars-sidebar-row-stub>").hasClass("active-filter")); // false because of topic
|
||||
|
||||
filter = new Filter([{operator: "stream", operand: "cars"}]);
|
||||
filter = new Filter([{operator: "stream", operand: carSub.stream_id.toString()}]);
|
||||
stream_list.handle_narrow_activated(filter);
|
||||
assert.ok(!$("ul.filters li").hasClass("active-filter"));
|
||||
assert.ok($("<cars-sidebar-row-stub>").hasClass("active-filter"));
|
||||
|
|
Loading…
Reference in New Issue