narrow: Extract narrow_title module.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
Anders Kaseorg 2023-10-05 14:18:00 -07:00 committed by Anders Kaseorg
parent b6a25840a1
commit d5064fc7b2
11 changed files with 146 additions and 135 deletions

View File

@ -140,6 +140,7 @@ EXEMPT_FILES = make_set(
"web/src/muted_users_ui.js", "web/src/muted_users_ui.js",
"web/src/narrow.js", "web/src/narrow.js",
"web/src/narrow_history.js", "web/src/narrow_history.js",
"web/src/narrow_title.js",
"web/src/navbar_alerts.js", "web/src/navbar_alerts.js",
"web/src/navigate.js", "web/src/navigate.js",
"web/src/notifications.js", "web/src/notifications.js",

View File

@ -15,7 +15,6 @@ import * as condense from "./condense";
import {Filter} from "./filter"; import {Filter} from "./filter";
import * as hash_parser from "./hash_parser"; import * as hash_parser from "./hash_parser";
import * as hashchange from "./hashchange"; import * as hashchange from "./hashchange";
import {$t} from "./i18n";
import * as inbox_ui from "./inbox_ui"; import * as inbox_ui from "./inbox_ui";
import * as inbox_util from "./inbox_util"; import * as inbox_util from "./inbox_util";
import * as left_sidebar_navigation_area from "./left_sidebar_navigation_area"; import * as left_sidebar_navigation_area from "./left_sidebar_navigation_area";
@ -32,7 +31,7 @@ import * as message_view_header from "./message_view_header";
import * as narrow_banner from "./narrow_banner"; import * as narrow_banner from "./narrow_banner";
import * as narrow_history from "./narrow_history"; import * as narrow_history from "./narrow_history";
import * as narrow_state from "./narrow_state"; import * as narrow_state from "./narrow_state";
import * as notifications from "./notifications"; import * as narrow_title from "./narrow_title";
import {page_params} from "./page_params"; import {page_params} from "./page_params";
import * as people from "./people"; import * as people from "./people";
import * as pm_list from "./pm_list"; import * as pm_list from "./pm_list";
@ -76,78 +75,6 @@ export function save_pre_narrow_offset_for_reload() {
export let has_shown_message_list_view = false; export let has_shown_message_list_view = false;
export function compute_narrow_title(filter) {
if (filter === undefined) {
// "All messages" and "Recent conversations" views have
// an `undefined` filter.
if (recent_view_util.is_visible()) {
return $t({defaultMessage: "Recent conversations"});
}
if (inbox_util.is_visible()) {
return $t({defaultMessage: "Inbox"});
}
}
const filter_title = filter.get_title();
if (filter_title === undefined) {
// Default result for uncommon narrow/search views.
return $t({defaultMessage: "Search results"});
}
if (filter.has_operator("stream")) {
if (!filter._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.
return filter_title;
}
if (filter.has_operator("topic")) {
const topic_name = filter.operands("topic")[0];
return "#" + filter_title + " > " + topic_name;
}
return "#" + filter_title;
}
if (filter.has_operator("dm")) {
const emails = filter.operands("dm")[0];
const user_ids = people.emails_strings_to_user_ids_string(emails);
if (user_ids !== undefined) {
return people.get_recipients(user_ids);
}
if (emails.includes(",")) {
return $t({defaultMessage: "Invalid users"});
}
return $t({defaultMessage: "Invalid user"});
}
if (filter.has_operator("sender")) {
const user = people.get_by_email(filter.operands("sender")[0]);
if (user) {
if (people.is_my_user_id(user.user_id)) {
return $t({defaultMessage: "Messages sent by you"});
}
return $t(
{defaultMessage: "Messages sent by {sender}"},
{
sender: user.full_name,
},
);
}
return $t({defaultMessage: "Invalid user"});
}
return filter_title;
}
export let narrow_title = "home";
export function update_narrow_title(filter) {
narrow_title = compute_narrow_title(filter);
notifications.redraw_title();
}
export function reset_ui_state() { export function reset_ui_state() {
// Resets the state of various visual UI elements that are // Resets the state of various visual UI elements that are
// a function of the current narrow. // a function of the current narrow.
@ -1015,7 +942,7 @@ function handle_post_view_change(msg_list) {
compose_closed_ui.update_reply_recipient_label(); compose_closed_ui.update_reply_recipient_label();
message_view_header.render_title_area(); message_view_header.render_title_area();
update_narrow_title(filter); narrow_title.update_narrow_title(filter);
left_sidebar_navigation_area.handle_narrow_activated(filter); left_sidebar_navigation_area.handle_narrow_activated(filter);
stream_list.handle_narrow_activated(filter); stream_list.handle_narrow_activated(filter);
pm_list.handle_narrow_activated(filter); pm_list.handle_narrow_activated(filter);

117
web/src/narrow_title.js Normal file
View File

@ -0,0 +1,117 @@
import * as favicon from "./favicon";
import {$t} from "./i18n";
import * as inbox_util from "./inbox_util";
import {page_params} from "./page_params";
import * as people from "./people";
import * as recent_view_util from "./recent_view_util";
import * as unread from "./unread";
export let unread_count = 0;
let pm_count = 0;
export let narrow_title = "home";
export function compute_narrow_title(filter) {
if (filter === undefined) {
// "All messages" and "Recent conversations" views have
// an `undefined` filter.
if (recent_view_util.is_visible()) {
return $t({defaultMessage: "Recent conversations"});
}
if (inbox_util.is_visible()) {
return $t({defaultMessage: "Inbox"});
}
}
const filter_title = filter.get_title();
if (filter_title === undefined) {
// Default result for uncommon narrow/search views.
return $t({defaultMessage: "Search results"});
}
if (filter.has_operator("stream")) {
if (!filter._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.
return filter_title;
}
if (filter.has_operator("topic")) {
const topic_name = filter.operands("topic")[0];
return "#" + filter_title + " > " + topic_name;
}
return "#" + filter_title;
}
if (filter.has_operator("dm")) {
const emails = filter.operands("dm")[0];
const user_ids = people.emails_strings_to_user_ids_string(emails);
if (user_ids !== undefined) {
return people.get_recipients(user_ids);
}
if (emails.includes(",")) {
return $t({defaultMessage: "Invalid users"});
}
return $t({defaultMessage: "Invalid user"});
}
if (filter.has_operator("sender")) {
const user = people.get_by_email(filter.operands("sender")[0]);
if (user) {
if (people.is_my_user_id(user.user_id)) {
return $t({defaultMessage: "Messages sent by you"});
}
return $t(
{defaultMessage: "Messages sent by {sender}"},
{
sender: user.full_name,
},
);
}
return $t({defaultMessage: "Invalid user"});
}
return filter_title;
}
export function redraw_title() {
// Update window title to reflect unread messages in current view
const new_title =
(unread_count ? "(" + unread_count + ") " : "") +
narrow_title +
" - " +
page_params.realm_name +
" - " +
"Zulip";
document.title = new_title;
}
export function update_unread_counts(counts) {
const new_unread_count = unread.calculate_notifiable_count(counts);
const new_pm_count = counts.direct_message_count;
if (new_unread_count === unread_count && new_pm_count === pm_count) {
return;
}
unread_count = new_unread_count;
pm_count = new_pm_count;
// Indicate the message count in the favicon
favicon.update_favicon(unread_count, pm_count);
// Notify the current desktop app's UI about the new unread count.
if (window.electron_bridge !== undefined) {
window.electron_bridge.send_event("total_unread_count", unread_count);
}
// TODO: Add a `window.electron_bridge.updateDirectMessageCount(new_pm_count);` call?
redraw_title();
}
export function update_narrow_title(filter) {
narrow_title = compute_narrow_title(filter);
redraw_title();
}

View File

@ -6,14 +6,12 @@ import render_unmute_topic_banner from "../templates/compose_banner/unmute_topic
import * as alert_words from "./alert_words"; import * as alert_words from "./alert_words";
import * as blueslip from "./blueslip"; import * as blueslip from "./blueslip";
import * as compose_banner from "./compose_banner"; import * as compose_banner from "./compose_banner";
import * as favicon from "./favicon";
import * as hash_util from "./hash_util"; import * as hash_util from "./hash_util";
import {$t} from "./i18n"; import {$t} from "./i18n";
import * as message_lists from "./message_lists"; import * as message_lists from "./message_lists";
import * as message_parser from "./message_parser"; import * as message_parser from "./message_parser";
import * as narrow from "./narrow"; import * as narrow from "./narrow";
import * as narrow_state from "./narrow_state"; import * as narrow_state from "./narrow_state";
import {page_params} from "./page_params";
import * as people from "./people"; import * as people from "./people";
import * as spoilers from "./spoilers"; import * as spoilers from "./spoilers";
import * as stream_data from "./stream_data"; import * as stream_data from "./stream_data";
@ -102,45 +100,6 @@ export function permission_state() {
return NotificationAPI.permission; return NotificationAPI.permission;
} }
let unread_count = 0;
let pm_count = 0;
export function redraw_title() {
// Update window title to reflect unread messages in current view
const new_title =
(unread_count ? "(" + unread_count + ") " : "") +
narrow.narrow_title +
" - " +
page_params.realm_name +
" - " +
"Zulip";
document.title = new_title;
}
export function update_unread_counts(counts) {
const new_unread_count = unread.calculate_notifiable_count(counts);
const new_pm_count = counts.direct_message_count;
if (new_unread_count === unread_count && new_pm_count === pm_count) {
return;
}
unread_count = new_unread_count;
pm_count = new_pm_count;
// Indicate the message count in the favicon
favicon.update_favicon(unread_count, pm_count);
// Notify the current desktop app's UI about the new unread count.
if (window.electron_bridge !== undefined) {
window.electron_bridge.send_event("total_unread_count", unread_count);
}
// TODO: Add a `window.electron_bridge.updateDirectMessageCount(new_pm_count);` call?
redraw_title();
}
function notify_unmute(muted_narrow, stream_id, topic_name) { function notify_unmute(muted_narrow, stream_id, topic_name) {
const $unmute_notification = $( const $unmute_notification = $(
render_unmute_topic_banner({ render_unmute_topic_banner({

View File

@ -28,6 +28,7 @@ import * as message_lists from "./message_lists";
import * as message_live_update from "./message_live_update"; import * as message_live_update from "./message_live_update";
import * as muted_users_ui from "./muted_users_ui"; import * as muted_users_ui from "./muted_users_ui";
import * as narrow_state from "./narrow_state"; import * as narrow_state from "./narrow_state";
import * as narrow_title from "./narrow_title";
import * as navbar_alerts from "./navbar_alerts"; import * as navbar_alerts from "./navbar_alerts";
import * as notifications from "./notifications"; import * as notifications from "./notifications";
import * as overlays from "./overlays"; import * as overlays from "./overlays";
@ -224,7 +225,7 @@ export function dispatch_normal_event(event) {
move_messages_within_stream_limit_seconds: message_edit.update_inline_topic_edit_ui, move_messages_within_stream_limit_seconds: message_edit.update_inline_topic_edit_ui,
message_retention_days: noop, message_retention_days: noop,
move_messages_between_streams_policy: noop, move_messages_between_streams_policy: noop,
name: notifications.redraw_title, name: narrow_title.redraw_title,
name_changes_disabled: settings_account.update_name_change_display, name_changes_disabled: settings_account.update_name_change_display,
notifications_stream_id: stream_ui_updates.update_announce_stream_option, notifications_stream_id: stream_ui_updates.update_announce_stream_option,
org_type: noop, org_type: noop,

View File

@ -67,6 +67,7 @@ import * as muted_users from "./muted_users";
import * as narrow from "./narrow"; import * as narrow from "./narrow";
import * as narrow_history from "./narrow_history"; import * as narrow_history from "./narrow_history";
import * as narrow_state from "./narrow_state"; import * as narrow_state from "./narrow_state";
import * as narrow_title from "./narrow_title";
import * as navbar_alerts from "./navbar_alerts"; import * as navbar_alerts from "./navbar_alerts";
import * as navigate from "./navigate"; import * as navigate from "./navigate";
import * as notifications from "./notifications"; import * as notifications from "./notifications";
@ -383,7 +384,7 @@ function initialize_unread_ui() {
); );
unread_ui.register_update_unread_counts_hook(() => topic_list.update()); unread_ui.register_update_unread_counts_hook(() => topic_list.update());
unread_ui.register_update_unread_counts_hook((counts) => unread_ui.register_update_unread_counts_hook((counts) =>
notifications.update_unread_counts(counts), narrow_title.update_unread_counts(counts),
); );
unread_ui.register_update_unread_counts_hook(inbox_ui.update); unread_ui.register_update_unread_counts_hook(inbox_ui.update);

View File

@ -3,6 +3,7 @@ import $ from "jquery";
import * as message_view_header from "./message_view_header"; import * as message_view_header from "./message_view_header";
import * as narrow from "./narrow"; import * as narrow from "./narrow";
import * as narrow_state from "./narrow_state"; import * as narrow_state from "./narrow_state";
import * as narrow_title from "./narrow_title";
import * as navigate from "./navigate"; import * as navigate from "./navigate";
import * as pm_list from "./pm_list"; import * as pm_list from "./pm_list";
import * as resize from "./resize"; import * as resize from "./resize";
@ -35,7 +36,7 @@ export function show(opts) {
unread_ui.hide_unread_banner(); unread_ui.hide_unread_banner();
opts.update_compose(); opts.update_compose();
narrow_state.reset_current_filter(); narrow_state.reset_current_filter();
narrow.update_narrow_title(narrow_state.filter()); narrow_title.update_narrow_title(narrow_state.filter());
message_view_header.render_title_area(); message_view_header.render_title_area();
narrow.handle_middle_pane_transition(); narrow.handle_middle_pane_transition();
search.clear_search_form(); search.clear_search_form();

View File

@ -34,6 +34,7 @@ const message_events = mock_esm("../src/message_events");
const message_lists = mock_esm("../src/message_lists"); const message_lists = mock_esm("../src/message_lists");
const user_topics_ui = mock_esm("../src/user_topics_ui"); const user_topics_ui = mock_esm("../src/user_topics_ui");
const muted_users_ui = mock_esm("../src/muted_users_ui"); const muted_users_ui = mock_esm("../src/muted_users_ui");
const narrow_title = mock_esm("../src/narrow_title");
const notifications = mock_esm("../src/notifications"); const notifications = mock_esm("../src/notifications");
const pm_list = mock_esm("../src/pm_list"); const pm_list = mock_esm("../src/pm_list");
const reactions = mock_esm("../src/reactions"); const reactions = mock_esm("../src/reactions");
@ -420,7 +421,7 @@ run_test("realm settings", ({override}) => {
override(settings_invites, "update_invite_user_panel", noop); override(settings_invites, "update_invite_user_panel", noop);
override(sidebar_ui, "update_invite_user_option", noop); override(sidebar_ui, "update_invite_user_option", noop);
override(gear_menu, "initialize", noop); override(gear_menu, "initialize", noop);
override(notifications, "redraw_title", noop); override(narrow_title, "redraw_title", noop);
function test_electron_dispatch(event, fake_send_event) { function test_electron_dispatch(event, fake_send_event) {
with_overrides(({override}) => { with_overrides(({override}) => {

View File

@ -16,6 +16,7 @@ const people = zrequire("people");
const stream_data = zrequire("stream_data"); const stream_data = zrequire("stream_data");
const {Filter} = zrequire("../src/filter"); const {Filter} = zrequire("../src/filter");
const narrow = zrequire("narrow"); const narrow = zrequire("narrow");
const narrow_title = zrequire("narrow_title");
const settings_config = zrequire("settings_config"); const settings_config = zrequire("settings_config");
const recent_view_util = zrequire("recent_view_util"); const recent_view_util = zrequire("recent_view_util");
const inbox_util = zrequire("inbox_util"); const inbox_util = zrequire("inbox_util");
@ -773,22 +774,22 @@ run_test("narrow_compute_title", () => {
filter = undefined; filter = undefined;
recent_view_util.set_visible(true); recent_view_util.set_visible(true);
inbox_util.set_visible(false); inbox_util.set_visible(false);
assert.equal(narrow.compute_narrow_title(filter), "translated: Recent conversations"); assert.equal(narrow_title.compute_narrow_title(filter), "translated: Recent conversations");
recent_view_util.set_visible(false); recent_view_util.set_visible(false);
inbox_util.set_visible(true); inbox_util.set_visible(true);
assert.equal(narrow.compute_narrow_title(filter), "translated: Inbox"); assert.equal(narrow_title.compute_narrow_title(filter), "translated: Inbox");
inbox_util.set_visible(false); inbox_util.set_visible(false);
filter = new Filter([{operator: "in", operand: "home"}]); filter = new Filter([{operator: "in", operand: "home"}]);
assert.equal(narrow.compute_narrow_title(filter), "translated: All messages"); assert.equal(narrow_title.compute_narrow_title(filter), "translated: All messages");
// Search & uncommon narrows // Search & uncommon narrows
filter = new Filter([{operator: "search", operand: "potato"}]); filter = new Filter([{operator: "search", operand: "potato"}]);
assert.equal(narrow.compute_narrow_title(filter), "translated: Search results"); assert.equal(narrow_title.compute_narrow_title(filter), "translated: Search results");
filter = new Filter([{operator: "sender", operand: "me"}]); filter = new Filter([{operator: "sender", operand: "me"}]);
assert.equal(narrow.compute_narrow_title(filter), "translated: Messages sent by you"); assert.equal(narrow_title.compute_narrow_title(filter), "translated: Messages sent by you");
// Stream narrows // Stream narrows
const sub = { const sub = {
@ -801,13 +802,13 @@ run_test("narrow_compute_title", () => {
{operator: "stream", operand: "foo"}, {operator: "stream", operand: "foo"},
{operator: "topic", operand: "bar"}, {operator: "topic", operand: "bar"},
]); ]);
assert.equal(narrow.compute_narrow_title(filter), "#Foo > 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"}]);
assert.equal(narrow.compute_narrow_title(filter), "#Foo"); assert.equal(narrow_title.compute_narrow_title(filter), "#Foo");
filter = new Filter([{operator: "stream", operand: "Elephant"}]); filter = new Filter([{operator: "stream", operand: "Elephant"}]);
assert.equal(narrow.compute_narrow_title(filter), "translated: Unknown stream #Elephant"); assert.equal(narrow_title.compute_narrow_title(filter), "translated: Unknown stream #Elephant");
// Direct messages with narrows // Direct messages with narrows
const joe = { const joe = {
@ -818,14 +819,14 @@ run_test("narrow_compute_title", () => {
people.add_active_user(joe); people.add_active_user(joe);
filter = new Filter([{operator: "dm", operand: "joe@example.com"}]); filter = new Filter([{operator: "dm", operand: "joe@example.com"}]);
assert.equal(narrow.compute_narrow_title(filter), "joe"); assert.equal(narrow_title.compute_narrow_title(filter), "joe");
filter = new Filter([{operator: "dm", operand: "joe@example.com,sally@doesnotexist.com"}]); filter = new Filter([{operator: "dm", operand: "joe@example.com,sally@doesnotexist.com"}]);
blueslip.expect("warn", "Unknown emails"); blueslip.expect("warn", "Unknown emails");
assert.equal(narrow.compute_narrow_title(filter), "translated: Invalid users"); assert.equal(narrow_title.compute_narrow_title(filter), "translated: Invalid users");
blueslip.reset(); blueslip.reset();
filter = new Filter([{operator: "dm", operand: "sally@doesnotexist.com"}]); filter = new Filter([{operator: "dm", operand: "sally@doesnotexist.com"}]);
blueslip.expect("warn", "Unknown emails"); blueslip.expect("warn", "Unknown emails");
assert.equal(narrow.compute_narrow_title(filter), "translated: Invalid user"); assert.equal(narrow_title.compute_narrow_title(filter), "translated: Invalid user");
}); });

View File

@ -29,7 +29,7 @@ const message_feed_top_notices = mock_esm("../src/message_feed_top_notices");
const message_feed_loading = mock_esm("../src/message_feed_loading"); const message_feed_loading = mock_esm("../src/message_feed_loading");
const message_view_header = mock_esm("../src/message_view_header"); const message_view_header = mock_esm("../src/message_view_header");
const narrow_history = mock_esm("../src/narrow_history"); const narrow_history = mock_esm("../src/narrow_history");
const notifications = mock_esm("../src/notifications"); const narrow_title = mock_esm("../src/narrow_title");
const stream_list = mock_esm("../src/stream_list"); const stream_list = mock_esm("../src/stream_list");
const left_sidebar_navigation_area = mock_esm("../src/left_sidebar_navigation_area"); const left_sidebar_navigation_area = mock_esm("../src/left_sidebar_navigation_area");
const typing_events = mock_esm("../src/typing_events"); const typing_events = mock_esm("../src/typing_events");
@ -86,7 +86,7 @@ function test_helper({override}) {
stub(hashchange, "save_narrow"); stub(hashchange, "save_narrow");
stub(message_feed_loading, "hide_indicators"); stub(message_feed_loading, "hide_indicators");
stub(message_feed_top_notices, "hide_top_of_narrow_notices"); stub(message_feed_top_notices, "hide_top_of_narrow_notices");
stub(notifications, "redraw_title"); stub(narrow_title, "update_narrow_title");
stub(stream_list, "handle_narrow_activated"); stub(stream_list, "handle_narrow_activated");
stub(message_view_header, "render_title_area"); stub(message_view_header, "render_title_area");
stub(left_sidebar_navigation_area, "handle_narrow_activated"); stub(left_sidebar_navigation_area, "handle_narrow_activated");
@ -193,7 +193,7 @@ run_test("basics", ({override}) => {
[compose_closed_ui, "update_buttons_for_stream"], [compose_closed_ui, "update_buttons_for_stream"],
[compose_closed_ui, "update_reply_recipient_label"], [compose_closed_ui, "update_reply_recipient_label"],
[message_view_header, "render_title_area"], [message_view_header, "render_title_area"],
[notifications, "redraw_title"], [narrow_title, "update_narrow_title"],
[left_sidebar_navigation_area, "handle_narrow_activated"], [left_sidebar_navigation_area, "handle_narrow_activated"],
[stream_list, "handle_narrow_activated"], [stream_list, "handle_narrow_activated"],
[compose_actions, "on_narrow"], [compose_actions, "on_narrow"],

View File

@ -142,11 +142,13 @@ mock_esm("../src/user_topics", {
all_visibility_policies, all_visibility_policies,
}); });
const narrow = mock_esm("../src/narrow", { const narrow = mock_esm("../src/narrow", {
update_narrow_title: noop,
hide_unread_banner: noop, hide_unread_banner: noop,
handle_middle_pane_transition: noop, handle_middle_pane_transition: noop,
has_shown_message_list_view: true, has_shown_message_list_view: true,
}); });
mock_esm("../src/narrow_title", {
update_narrow_title() {},
});
mock_esm("../src/pm_list", { mock_esm("../src/pm_list", {
update_private_messages: noop, update_private_messages: noop,
handle_message_view_deactivated: noop, handle_message_view_deactivated: noop,