left_sidebar: Improve mentions in muted topics.

When there are only muted unread mentions in a stream, show `@` icon
and unread count in faded style, also align the `@` on more topics
with no unead counter on it.

If there are only muted unread messages without mentions don't show
the unread counter on the stream.

Fixes #25382.
This commit is contained in:
Hardik Dharmani 2023-05-20 02:01:46 +05:30 committed by Tim Abbott
parent 8c6f9b3f95
commit d9716bc189
4 changed files with 67 additions and 8 deletions

View File

@ -37,6 +37,7 @@ export function update_count_in_dom(
stream_counts,
stream_has_any_unread_mention_messages,
stream_has_any_unmuted_unread_mention,
stream_has_only_muted_unread_mention,
) {
// The subscription_block properly excludes the topic list,
// and it also has sensitive margins related to whether the
@ -50,8 +51,14 @@ export function update_count_in_dom(
if (stream_has_any_unmuted_unread_mention) {
$subscription_block.addClass("has-unmuted-mentions");
$subscription_block.removeClass("has-only-muted-mentions");
} else {
$subscription_block.removeClass("has-unmuted-mentions");
if (!stream_counts.stream_is_muted && stream_has_only_muted_unread_mention) {
$subscription_block.addClass("has-only-muted-mentions");
} else {
$subscription_block.removeClass("has-only-muted-mentions");
}
}
// Here we set the count and compute the values of two classes:
@ -64,16 +71,32 @@ export function update_count_in_dom(
ui_util.update_unread_count_in_dom($subscription_block, stream_counts.unmuted_count);
$subscription_block.addClass("stream-with-count");
$subscription_block.removeClass("has-unmuted-unreads");
$subscription_block.removeClass("has-only-muted-unreads");
} else if (stream_counts.unmuted_count > 0 && stream_counts.stream_is_muted) {
// Muted stream, has unmuted unreads.
ui_util.update_unread_count_in_dom($subscription_block, stream_counts.unmuted_count);
$subscription_block.addClass("stream-with-count");
$subscription_block.addClass("has-unmuted-unreads");
$subscription_block.removeClass("has-only-muted-unreads");
} else if (stream_counts.muted_count > 0 && stream_counts.stream_is_muted) {
// Muted stream, only muted unreads.
ui_util.update_unread_count_in_dom($subscription_block, stream_counts.muted_count);
$subscription_block.addClass("stream-with-count");
$subscription_block.removeClass("has-unmuted-unreads");
$subscription_block.removeClass("has-only-muted-unreads");
} else if (
stream_counts.muted_count > 0 &&
!stream_counts.stream_is_muted &&
stream_has_only_muted_unread_mention
) {
// Normal stream, only muted unreads, including a mention:
// Display the mention, faded, and a faded unread count too,
// so that we don't weirdly show the mention indication
// without an unread count.
ui_util.update_unread_count_in_dom($subscription_block, stream_counts.muted_count);
$subscription_block.removeClass("has-unmuted-unreads");
$subscription_block.addClass("stream-with-count");
$subscription_block.addClass("has-only-muted-unreads");
} else if (stream_counts.muted_count > 0 && !stream_counts.stream_is_muted) {
// Normal stream, only muted unreads: display nothing. The
// current thinking is displaying those counts with muted
@ -85,6 +108,7 @@ export function update_count_in_dom(
// No unreads: display nothing.
ui_util.update_unread_count_in_dom($subscription_block, 0);
$subscription_block.removeClass("has-unmuted-unreads");
$subscription_block.removeClass("has-only-muted-unreads");
$subscription_block.removeClass("stream-with-count");
}
}
@ -396,11 +420,16 @@ class StreamSidebarRow {
const stream_has_any_unmuted_unread_mention = unread.stream_has_any_unmuted_mentions(
this.sub.stream_id,
);
const stream_has_only_muted_unread_mentions =
!this.sub.is_muted &&
stream_has_any_unread_mention_messages &&
!stream_has_any_unmuted_unread_mention;
update_count_in_dom(
this.$list_item,
count,
stream_has_any_unread_mention_messages,
stream_has_any_unmuted_unread_mention,
stream_has_only_muted_unread_mentions,
);
}
}
@ -443,6 +472,7 @@ function set_stream_unread_count(
count,
stream_has_any_unread_mention_messages,
stream_has_any_unmuted_unread_mention,
stream_has_only_muted_unread_mentions,
) {
const $stream_li = get_stream_li(stream_id);
if (!$stream_li) {
@ -456,6 +486,7 @@ function set_stream_unread_count(
count,
stream_has_any_unread_mention_messages,
stream_has_any_unmuted_unread_mention,
stream_has_only_muted_unread_mentions,
);
}
@ -492,11 +523,16 @@ export function update_dom_with_unread_counts(counts) {
counts.streams_with_mentions.includes(stream_id);
const stream_has_any_unmuted_unread_mention =
counts.streams_with_unmuted_mentions.includes(stream_id);
const stream_has_only_muted_unread_mentions =
!sub_store.get(stream_id).is_muted &&
stream_has_any_unread_mention_messages &&
!stream_has_any_unmuted_unread_mention;
set_stream_unread_count(
stream_id,
count,
stream_has_any_unread_mention_messages,
stream_has_any_unmuted_unread_mention,
stream_has_only_muted_unread_mentions,
);
}
}

View File

@ -403,11 +403,13 @@ class UnreadTopicCounter {
}
get_streams_with_unread_mentions() {
const streams_with_mentions = new Set();
// Collect the set of streams containing at least one mention.
// Collect the set of streams containing at least one unread
// mention, without considering muting.
// We can do this efficiently, since unread_mentions_counter
// contains all unread message IDs, and we use stream_ids as
// bucket keys in our outer bucketer.
const streams_with_mentions = new Set();
for (const message_id of unread_mentions_counter) {
const stream_id = this.bucketer.reverse_lookup.get(message_id);
@ -422,9 +424,10 @@ class UnreadTopicCounter {
}
get_streams_with_unmuted_mentions() {
const streams_with_unmuted_mentions = new Set();
// Collect the set of streams containing at least one mention
// in an unmuted topic within a muted stream.
// that is not in a muted topic or non-unmuted topic in a
// muted stream.
const streams_with_unmuted_mentions = new Set();
for (const message_id of unread_mentions_counter) {
const stream_id = this.bucketer.reverse_lookup.get(message_id);
if (stream_id === undefined) {
@ -434,8 +437,15 @@ class UnreadTopicCounter {
const stream_bucketer = this.bucketer.get_bucket(stream_id);
const topic = stream_bucketer.reverse_lookup.get(message_id);
if (user_topics.is_topic_unmuted(stream_id, topic)) {
streams_with_unmuted_mentions.add(stream_id);
const stream_is_muted = sub_store.get(stream_id)?.is_muted;
if (stream_is_muted) {
if (user_topics.is_topic_unmuted(stream_id, topic)) {
streams_with_unmuted_mentions.add(stream_id);
}
} else {
if (!user_topics.is_topic_muted(stream_id, topic)) {
streams_with_unmuted_mentions.add(stream_id);
}
}
}
return streams_with_unmuted_mentions;

View File

@ -353,6 +353,16 @@ ul.filters {
margin-bottom: 10px;
}
.has-only-muted-unreads {
.unread_count {
opacity: 0.5;
}
}
.has-only-muted-mentions .unread_mention_info {
opacity: 0.5;
}
/* This is a noop in the current design, because unread counts for
muted streams have the same opacity, but the logic is here to
be explicit and because the design may change in the future. */
@ -765,6 +775,10 @@ li.topic-list-item {
visibility: hidden;
}
.zero-topic-unreads.show-more-topics .topic-box {
margin-right: 30px;
}
.searching-for-more-topics img {
height: 16px;
margin-left: 6px;

View File

@ -15,7 +15,6 @@ page_params.realm_users = [];
// We use this with override.
let num_unread_for_stream;
let stream_has_any_unread_mentions;
let stream_has_any_unmuted_mentions;
const noop = () => {};
mock_esm("../src/narrow_state", {
@ -36,7 +35,7 @@ mock_esm("../src/unread", {
muted_count: 0,
}),
stream_has_any_unread_mentions: () => stream_has_any_unread_mentions,
stream_has_any_unmuted_mentions: () => stream_has_any_unmuted_mentions,
stream_has_any_unmuted_mentions: () => noop,
});
const {Filter} = zrequire("../src/filter");