mirror of
https://github.com/zulip/zulip.git
synced 2025-10-30 19:43:47 +00:00
184 lines
5.8 KiB
TypeScript
184 lines
5.8 KiB
TypeScript
export function get_hash_category(hash?: string): string {
|
|
// given "#channels/subscribed", returns "channels"
|
|
return hash ? hash.replace(/^#/, "").split(/\//)[0]! : "";
|
|
}
|
|
|
|
export function get_hash_section(hash?: string): string {
|
|
// given "#settings/profile", returns "profile"
|
|
// given '#channels/5/social", returns "5"
|
|
if (!hash) {
|
|
return "";
|
|
}
|
|
|
|
const parts = hash.replace(/\/$/, "").split(/\//);
|
|
|
|
return parts[1] ?? "";
|
|
}
|
|
|
|
function get_nth_hash_section(hash: string, n: number): string {
|
|
// given "#settings/profile" and n=1, returns "profile"
|
|
// given '#channels/5/social" and n=2, returns "social"
|
|
const parts = hash.replace(/\/$/, "").split(/\//);
|
|
return parts.at(n) ?? "";
|
|
}
|
|
|
|
export function get_current_nth_hash_section(n: number): string {
|
|
return get_nth_hash_section(window.location.hash, n);
|
|
}
|
|
|
|
export function get_current_hash_category(): string {
|
|
return get_hash_category(window.location.hash);
|
|
}
|
|
|
|
export function get_current_hash_section(): string {
|
|
return get_hash_section(window.location.hash);
|
|
}
|
|
|
|
export function is_same_server_message_link(url: string): boolean {
|
|
// A same server message link always has category `narrow`,
|
|
// section `channel` or `dm`, and ends with `/near/<message_id>`,
|
|
// where <message_id> is a sequence of digits.
|
|
return (
|
|
get_hash_category(url) === "narrow" &&
|
|
(get_hash_section(url) === "channel" || get_hash_section(url) === "dm") &&
|
|
get_nth_hash_section(url, -2) === "near" &&
|
|
/^\d+$/.test(get_nth_hash_section(url, -1))
|
|
);
|
|
}
|
|
|
|
export function is_overlay_hash(hash: string | undefined): boolean {
|
|
// Hash changes within this list are overlays and should not unnarrow (etc.)
|
|
const overlay_list = [
|
|
// In 2024, stream was renamed to channel in the Zulip API and UI.
|
|
// Because pre-change Welcome Bot and Notification Bot messages
|
|
// included links to "/#streams/all" and "/#streams/new", we'll
|
|
// need to support "streams" as an overlay hash as an alias for
|
|
// "channels" permanently.
|
|
"streams",
|
|
"channels",
|
|
"drafts",
|
|
"groups",
|
|
"settings",
|
|
"organization",
|
|
"invite",
|
|
"keyboard-shortcuts",
|
|
"message-formatting",
|
|
"search-operators",
|
|
"about-zulip",
|
|
"scheduled",
|
|
"reminders",
|
|
"user",
|
|
];
|
|
const main_hash = get_hash_category(hash);
|
|
|
|
return overlay_list.includes(main_hash);
|
|
}
|
|
|
|
// this finds the stream that is actively open in the settings and focused in
|
|
// the left side.
|
|
export function is_editing_stream(desired_stream_id: number): boolean {
|
|
const hash_components = window.location.hash.slice(1).split(/\//);
|
|
|
|
if (hash_components[0] !== "channels") {
|
|
return false;
|
|
}
|
|
|
|
if (!hash_components[2]) {
|
|
return false;
|
|
}
|
|
|
|
// if the string casted to a number is valid, and another component
|
|
// after exists then it's a stream name/id pair.
|
|
const stream_id = Number.parseFloat(hash_components[1]!);
|
|
|
|
return stream_id === desired_stream_id;
|
|
}
|
|
|
|
export function is_create_new_stream_narrow(): boolean {
|
|
return window.location.hash === "#channels/new";
|
|
}
|
|
|
|
// This checks whether the user is in the stream settings menu
|
|
// and is opening the 'Subscribers' tab on the right panel.
|
|
export function is_subscribers_section_opened_for_stream(): boolean {
|
|
const hash_components = window.location.hash.slice(1).split(/\//);
|
|
|
|
if (hash_components[0] !== "channels") {
|
|
return false;
|
|
}
|
|
if (!hash_components[3]) {
|
|
return false;
|
|
}
|
|
return hash_components[3] === "subscribers";
|
|
}
|
|
|
|
export function is_in_specified_hash_category(hash_categories: string[]): boolean {
|
|
const main_hash = get_hash_category(window.location.hash);
|
|
return hash_categories.includes(main_hash);
|
|
}
|
|
|
|
export function is_an_allowed_web_public_narrow(operator: string, operand: string): boolean {
|
|
if (operator === "is" && operand === "resolved") {
|
|
return true;
|
|
}
|
|
return allowed_web_public_narrow_operators.includes(operator);
|
|
}
|
|
|
|
export const allowed_web_public_narrow_operators = [
|
|
"channels",
|
|
"channel",
|
|
"streams",
|
|
"stream",
|
|
"topic",
|
|
"sender",
|
|
"has",
|
|
"search",
|
|
"near",
|
|
"id",
|
|
"with",
|
|
];
|
|
|
|
export function is_spectator_compatible(hash: string): boolean {
|
|
// Defines which views are supported for spectators.
|
|
// This implementation should agree with the similar function in zerver/lib/narrow.py.
|
|
const web_public_allowed_hashes = [
|
|
"",
|
|
// full #narrow hash handled in filter.is_spectator_compatible
|
|
"narrow",
|
|
// TODO/compatibility: #recent_topics was renamed to #recent
|
|
// in 2022. We should support the old URL fragment at least
|
|
// until one cannot directly upgrade from Zulip 5.x.
|
|
"recent_topics",
|
|
"recent",
|
|
"keyboard-shortcuts",
|
|
"message-formatting",
|
|
"search-operators",
|
|
// TODO/compatibility: #all_messages was renamed to #feed
|
|
// in 2024. We should support the old URL fragment at least
|
|
// until one cannot directly upgrade from Zulip 8.x.
|
|
"all_messages",
|
|
"feed",
|
|
"about-zulip",
|
|
"topics",
|
|
];
|
|
|
|
const main_hash = get_hash_category(hash);
|
|
|
|
if (main_hash === "narrow") {
|
|
const hash_components = hash
|
|
.split(/\//)
|
|
.filter((hash_component) => hash_component !== "#narrow");
|
|
|
|
for (let i = 0; i < hash_components.length; i += 2) {
|
|
const hash_section = hash_components[i]!.replace(/^-/, "");
|
|
const second_hash_section = hash_components[i + 1]!;
|
|
if (!is_an_allowed_web_public_narrow(hash_section, second_hash_section)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
return web_public_allowed_hashes.includes(main_hash);
|
|
}
|