user_settings: Add new user setting to show/hide unread counts on streams.

Added a show_unread_counts personal user setting to the
Settings > Display settings > Advanced section which
lets user choose whether he/she wants to see unread messages
count on the left sidebar for streams.

This setting have three options,
"All Streams" - This will show unread messages count for all
streams.
"Unmuted Stream" - This will be default option and it will
only show unread messages count for unmuted streams.
"No Stream" - This option will not show unread messages count
on any stream.

Fixes #24149
This commit is contained in:
Lalit
2023-04-25 17:07:16 +05:30
committed by Tim Abbott
parent fb165f1901
commit 0e73b5547c
16 changed files with 165 additions and 8 deletions

View File

@@ -173,6 +173,8 @@ export function build_page() {
web_mark_read_on_scroll_policy_values:
settings_config.web_mark_read_on_scroll_policy_values,
user_list_style_values: settings_config.user_list_style_values,
web_stream_unreads_count_display_policy_values:
settings_config.web_stream_unreads_count_display_policy_values,
color_scheme_values: settings_config.color_scheme_values,
default_view_values: settings_config.default_view_values,
settings_object: realm_user_settings_defaults,

View File

@@ -39,6 +39,7 @@ export type RealmDefaultSettings = {
translate_emoticons: boolean;
twenty_four_hour_time: boolean;
user_list_style: boolean;
web_stream_unreads_count_display_policy: number;
web_mark_read_on_scroll_policy: number;
wildcard_mentions_notify: boolean;
};

View File

@@ -689,6 +689,7 @@ export function dispatch_normal_event(event) {
"translate_emoticons",
"display_emoji_reaction_users",
"user_list_style",
"web_stream_unreads_count_display_policy",
"starred_message_counts",
"send_stream_typing_notifications",
"send_private_typing_notifications",
@@ -735,6 +736,9 @@ export function dispatch_normal_event(event) {
stream_list.update_streams_sidebar();
stream_list_sort.set_filter_out_inactives();
}
if (event.property === "web_stream_unreads_count_display_policy") {
stream_list.update_dom_unread_counts_visibility();
}
if (event.property === "user_list_style") {
settings_display.report_user_list_style_change(
settings_display.user_settings_panel,

View File

@@ -99,6 +99,8 @@ export function build_page() {
web_mark_read_on_scroll_policy_values:
settings_config.web_mark_read_on_scroll_policy_values,
user_list_style_values: settings_config.user_list_style_values,
web_stream_unreads_count_display_policy_values:
settings_config.web_stream_unreads_count_display_policy_values,
color_scheme_values: settings_config.color_scheme_values,
default_view_values: settings_config.default_view_values,
twenty_four_hour_time_values: settings_config.twenty_four_hour_time_values,

View File

@@ -71,6 +71,21 @@ export const user_list_style_values = {
// },
};
export const web_stream_unreads_count_display_policy_values = {
all_streams: {
code: 1,
description: $t({defaultMessage: "All streams"}),
},
unmuted_streams: {
code: 2,
description: $t({defaultMessage: "Unmuted streams"}),
},
no_streams: {
code: 3,
description: $t({defaultMessage: "No streams"}),
},
};
export const default_view_values = {
recent_topics: {
code: "recent_topics",

View File

@@ -195,6 +195,24 @@ export function user_can_delete_own_message(): boolean {
return user_has_permission(page_params.realm_delete_own_message_policy);
}
export function should_mask_unread_count(sub_muted: boolean): boolean {
if (
user_settings.web_stream_unreads_count_display_policy ===
settings_config.web_stream_unreads_count_display_policy_values.no_streams.code
) {
return true;
}
if (
user_settings.web_stream_unreads_count_display_policy ===
settings_config.web_stream_unreads_count_display_policy_values.unmuted_streams.code
) {
return sub_muted;
}
return false;
}
export function using_dark_theme(): boolean {
if (user_settings.color_scheme === settings_config.color_scheme_values.night.code) {
return true;

View File

@@ -180,6 +180,10 @@ export function set_up(settings_panel) {
.find(`.setting_user_list_style_choice[value=${settings_object.user_list_style}]`)
.prop("checked", true);
$container
.find(".setting_web_stream_unreads_count_display_policy")
.val(settings_object.web_stream_unreads_count_display_policy);
if (for_realm_settings) {
// For the realm-level defaults page, we use the common
// settings_org.js handlers, so we can return early here.

View File

@@ -373,15 +373,17 @@ export function set_in_home_view(stream_id, in_home) {
function build_stream_sidebar_li(sub) {
const name = sub.name;
const is_muted = stream_data.is_muted(sub.stream_id);
const args = {
name,
id: sub.stream_id,
url: hash_util.by_stream_url(sub.stream_id),
is_muted: stream_data.is_muted(sub.stream_id) === true,
is_muted,
invite_only: sub.invite_only,
is_web_public: sub.is_web_public,
color: sub.color,
pin_to_top: sub.pin_to_top,
hide_unread_count: settings_data.should_mask_unread_count(is_muted),
};
const $list_item = $(render_stream_sidebar_row(args));
return $list_item;
@@ -535,6 +537,21 @@ export function update_dom_with_unread_counts(counts) {
}
}
export function update_dom_unread_counts_visibility() {
for (const stream of stream_sidebar.rows.values()) {
const $subscription_block = stream.get_li().find(".subscription_block");
const is_muted = stream_data.is_muted(stream.sub.stream_id);
const hide_count = settings_data.should_mask_unread_count(is_muted);
if (hide_count) {
$subscription_block.addClass("hide_unread_counts");
} else {
$subscription_block.removeClass("hide_unread_counts");
}
}
}
export function rename_stream(sub) {
// The sub object is expected to already have the updated name
build_stream_sidebar_row(sub);

View File

@@ -48,6 +48,7 @@ export type UserSettings = (StreamNotificationSettings &
presence_enabled: boolean;
realm_name_in_email_notifications_policy: number;
user_list_style: number;
web_stream_unreads_count_display_policy: number;
starred_message_counts: boolean;
translate_emoticons: boolean;
display_emoji_reaction_users: boolean;

View File

@@ -589,6 +589,15 @@ div.overlay {
opacity: 0.7;
}
.masked_unread_count {
float: right;
width: 8px;
height: 8px;
border-radius: 50%;
background-color: hsl(0deg 0% 80%);
display: none;
}
/* Implement the web app's default-hidden convention for alert
elements. Portico pages lack this CSS and thus show them by
default. */

View File

@@ -141,10 +141,6 @@ li.show-more-topics {
}
}
.subscription_block .unread_count {
margin-right: 15px;
}
.subscription_block {
margin-right: 25px;
margin-left: $far_left_gutter_size;
@@ -152,11 +148,67 @@ li.show-more-topics {
align-items: center;
white-space: nowrap;
& .unread_count {
margin-right: 15px;
}
& .masked_unread_count {
/* TODO: In theory this should be 19, to make it center aligned with
unread_count span which has a padding of 4px
horizontally in addition to 15px margin. But 18px looks
better centered. */
margin-right: 18px;
}
&.stream-with-count {
margin-right: 15px;
}
}
.stream-with-count.hide_unread_counts {
.masked_unread_count {
display: inline;
}
.unread_count {
display: none;
}
}
.narrow-filter
> .bottom_left_row:hover
> .stream-with-count.hide_unread_counts {
.masked_unread_count {
display: none;
}
.unread_count {
display: inline;
}
}
.stream-expanded {
.stream-with-count.hide_unread_counts {
.masked_unread_count {
display: none;
}
.unread_count {
display: inline;
}
}
}
.has-unmuted-unreads.hide_unread_counts {
.masked_unread_count {
display: none;
}
.unread_count {
display: inline;
}
}
.inactive_stream:not(.active-filter) {
opacity: 0.5;
}
@@ -390,6 +442,10 @@ ul.filters {
opacity: 0.5;
}
& .masked_unread_count {
opacity: 0.5;
}
.has-unmuted-unreads {
.unread_count {
opacity: 1;
@@ -473,7 +529,6 @@ li.active-sub-filter {
.top_left_row .unread_count {
margin-top: 2px;
display: none;
}
.top_left_starred_messages .unread_count,

View File

@@ -141,6 +141,13 @@
</select>
</div>
<div class="input-group">
<label for="web_stream_unreads_count_display_policy" class="dropdown-title">{{t "Show unread counts for" }}</label>
<select name="web_stream_unreads_count_display_policy" class="setting_web_stream_unreads_count_display_policy prop-element bootstrap-focus-style settings_select" id="{{prefix}}web_stream_unreads_count_display_policy" data-setting-widget-type="number">
{{> dropdown_options_widget option_values=web_stream_unreads_count_display_policy_values}}
</select>
</div>
{{#each display_settings.settings.user_display_settings}}
{{> settings_checkbox
setting_name=this

View File

@@ -2,7 +2,7 @@
<li class="narrow-filter{{#if is_muted}} out_of_home_view{{/if}}" data-stream-id="{{id}}">
<div class="bottom_left_row">
<div class="subscription_block selectable_sidebar_block">
<div class="subscription_block selectable_sidebar_block {{#if hide_unread_count}}hide_unread_counts{{/if}}">
<span class="stream-privacy-original-color-{{id}} stream-privacy filter-icon" style="color: {{color}}">
{{> stream_privacy }}
@@ -12,6 +12,7 @@
<span class="unread_mention_info"></span>
<span class="unread_count"></span>
<span class="masked_unread_count"></span>
</div>
<span class="stream-sidebar-menu-icon hidden-for-spectators"><i class="zulip-icon zulip-icon-ellipsis-v-solid" aria-hidden="true"></i></span>
</div>

View File

@@ -966,6 +966,16 @@ run_test("user_settings", ({override}) => {
assert_same(user_settings.demote_inactive_streams, 2);
}
{
const stub = make_stub();
event = event_fixtures.user_settings__web_stream_unreads_count_display_policy;
override(stream_list, "update_dom_unread_counts_visibility", stub.f);
user_settings.web_stream_unreads_count_display_policy = 1;
dispatch(event);
assert.equal(stub.num_calls, 1);
assert_same(user_settings.web_stream_unreads_count_display_policy, 2);
}
{
const stub = make_stub();
event = event_fixtures.user_settings__user_list_style;

View File

@@ -1031,6 +1031,13 @@ exports.fixtures = {
value: 1,
},
user_settings__web_stream_unreads_count_display_policy: {
type: "user_settings",
op: "update",
property: "web_stream_unreads_count_display_policy",
value: 2,
},
user_status__set_status_emoji: {
type: "user_status",
user_id: test_user.user_id,

View File

@@ -648,6 +648,8 @@ test_ui("separators_only_pinned", () => {
});
test_ui("rename_stream", ({mock_template}) => {
user_settings.web_stream_unreads_count_display_policy = 3;
create_stream_subheader({mock_template});
initialize_stream_data();
@@ -664,11 +666,12 @@ test_ui("rename_stream", ({mock_template}) => {
name: "Development",
id: 1000,
url: "#narrow/stream/1000-Development",
is_muted: false,
is_muted: undefined,
invite_only: undefined,
is_web_public: undefined,
color: payload.color,
pin_to_top: true,
hide_unread_count: true,
});
return {to_$: () => $li_stub};
});
@@ -722,6 +725,7 @@ test_ui("refresh_pin", ({override, override_rewire, mock_template}) => {
});
test_ui("create_initial_sidebar_rows", ({override, override_rewire, mock_template}) => {
user_settings.web_stream_unreads_count_display_policy = 2; // Test coverage for this setting.
initialize_stream_data();
const html_dict = new Map();