Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Navbar: Describe views in top navbar. #29824

Merged
merged 2 commits into from
May 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
26 changes: 25 additions & 1 deletion web/src/filter.ts
Expand Up @@ -912,7 +912,12 @@ export class Filter {
return "#"; // redirect to All
}

add_icon_data(context: {title: string; is_spectator: boolean}): IconData {
add_icon_data(context: {
title: string;
description?: string;
link?: string;
is_spectator: boolean;
}): IconData {
// We have special icons for the simple narrows available for the via sidebars.
const term_types = this.sorted_term_types();
let icon;
Expand Down Expand Up @@ -1046,6 +1051,25 @@ export class Filter {
return undefined;
}

get_description(): {description: string; link: string} | undefined {
const term_types = this.sorted_term_types();
switch (term_types[0]) {
case "is-mentioned":
return {
description: $t({defaultMessage: "Messages where you are mentioned."}),
link: "/help/view-your-mentions",
};
case "is-starred":
return {
description: $t({
defaultMessage: "Important messages, tasks, and other useful references.",
}),
link: "/help/star-a-message#view-your-starred-messages",
};
}
return undefined;
}

allow_use_first_unread_when_narrowing(): boolean {
return this.can_mark_messages_read() || this.has_operator("is");
}
Expand Down
43 changes: 38 additions & 5 deletions web/src/message_view_header.ts
Expand Up @@ -19,6 +19,8 @@ import type {StreamSubscription} from "./sub_store";

type MessageViewHeaderContext = {
title: string;
description?: string;
link?: string;
is_spectator?: boolean;
sub_count?: string | number;
formatted_sub_count?: string;
Expand All @@ -39,53 +41,84 @@ function get_message_view_header_context(filter: Filter | undefined): MessageVie
if (recent_view_util.is_visible()) {
return {
title: $t({defaultMessage: "Recent conversations"}),
description: $t({defaultMessage: "Overview of ongoing conversations."}),
zulip_icon: "recent",
link: "/help/recent-conversations",
};
}

if (inbox_util.is_visible()) {
return {
title: $t({defaultMessage: "Inbox"}),
description: $t({
defaultMessage: "Overview of your conversations with unread messages.",
}),
zulip_icon: "inbox",
link: "/help/inbox",
};
}
if (filter === undefined) {

// TODO: If we're not in the recent or inbox view, there should be
// a message feed with a declared filter in the center pane. But
// because of an initialization order bug, this function gets
// called with a filter of `undefined` when loading the web app
// with, say, inbox as the home view.
//
// TODO: Refactor this function to move the inbox/recent cases
// into the caller, and this function can always get a Filter object.
//
// TODO: This ideally doesn't need a special case, we can just use
// `filter.get_description` for it.
if (filter === undefined || filter.is_in_home()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

filter is only undefined on an initial load, a hash change (/#feed) presents a filter object, so this OR statement checks for that condition, so that the Combined feed gets its proper description.

return {
title: $t({defaultMessage: "Combined feed"}),
description: $t({
defaultMessage: "All your messages except those in muted channels and topics.",
}),
zulip_icon: "all-messages",
link: "/help/combined-feed",
};
}

const title = filter.get_title();
const description = filter.get_description()?.description;
const link = filter.get_description()?.link;
assert(title !== undefined);
const icon_data = filter.add_icon_data({
const context = filter.add_icon_data({
title,
description,
link,
is_spectator: page_params.is_spectator,
});

if (filter.has_operator("channel") && !filter._sub) {
return {
...icon_data,
...context,
sub_count: "0",
formatted_sub_count: "0",
rendered_narrow_description: $t({
defaultMessage: "This channel does not exist or is private.",
}),
};
}

if (filter._sub) {
// 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 {
...icon_data,
...context,
is_admin: current_user.is_admin,
rendered_narrow_description: current_stream.rendered_description,
sub_count,
stream: current_stream,
stream_settings_link: hash_util.channels_settings_edit_url(current_stream, "general"),
};
}
return icon_data;

return context;
}

export function colorize_message_view_header(): void {
Expand Down
5 changes: 5 additions & 0 deletions web/styles/message_view_header.css
Expand Up @@ -94,6 +94,11 @@
padding-left: 10px;
overflow: hidden;
text-overflow: ellipsis;

.help_link_widget,
.fa {
margin: 0;
}
}

/* The very last element in the navbar is the search icon, the second
Expand Down
9 changes: 9 additions & 0 deletions web/templates/navbar_icon_and_title.hbs
Expand Up @@ -4,3 +4,12 @@
<i class="fa fa-{{icon}}" aria-hidden="true"></i>
{{/if}}
<span class="message-header-navbar-title">{{title}}</span>
{{#if description}}
<span class="narrow_description rendered_markdown">{{description}}
{{#if link}}
<a class="help_link_widget" href="{{link}}" target="_blank" rel="noopener noreferrer">
<i class="fa fa-question-circle-o" aria-hidden="true"></i>
</a>
{{/if}}
</span>
{{/if}}
19 changes: 19 additions & 0 deletions web/tests/filter.test.js
Expand Up @@ -1628,11 +1628,26 @@ test("navbar_helpers", () => {
assert.deepEqual(filter.get_title(), test_case.title);
}

function test_get_description(test_case) {
const filter = new Filter(test_case.terms);
const description = filter.get_description();

if (test_case.description !== undefined && test_case.link !== undefined) {
assert.deepEqual(description, {
description: test_case.description,
link: test_case.link,
});
} else {
assert.strictEqual(description, undefined);
}
}

function test_helpers(test_case) {
// debugging tip: add a `console.log(test_case)` here
test_common_narrow(test_case);
test_add_icon_data(test_case);
test_get_title(test_case);
test_get_description(test_case);
test_redirect_url_with_search(test_case);
}

Expand Down Expand Up @@ -1703,6 +1718,8 @@ test("navbar_helpers", () => {
zulip_icon: "star-filled",
title: "translated: Starred messages",
redirect_url_with_search: "/#narrow/is/starred",
description: "translated: Important messages, tasks, and other useful references.",
link: "/help/star-a-message#view-your-starred-messages",
},
{
terms: in_home,
Expand Down Expand Up @@ -1731,6 +1748,8 @@ test("navbar_helpers", () => {
zulip_icon: "at-sign",
title: "translated: Mentions",
redirect_url_with_search: "/#narrow/is/mentioned",
description: "translated: Messages where you are mentioned.",
link: "/help/view-your-mentions",
},
{
terms: is_resolved,
Expand Down