mirror of
https://github.com/zulip/zulip.git
synced 2026-07-09 21:21:47 +08:00
When all the unread messages in a muted stream are in specifically muted topics, this ensures that the total unread count for the stream that the user sees before clicking "more topics" will match the total unreads number for the stream itself. This behavior is limited to muted streams, since in a normal / not muted stream, we don't display a "muted topics only" faded unread count by the stream's summary line to avoid distracting the user with it, we match that behavior for the "more topics" line. We also now display the `@` , again to ensure the stream's summary line never displays an `@` without some topic row having one.
168 lines
6.8 KiB
JavaScript
168 lines
6.8 KiB
JavaScript
import * as resolved_topic from "../shared/src/resolved_topic";
|
|
|
|
import * as hash_util from "./hash_util";
|
|
import * as narrow_state from "./narrow_state";
|
|
import * as stream_topic_history from "./stream_topic_history";
|
|
import * as sub_store from "./sub_store";
|
|
import * as unread from "./unread";
|
|
import * as user_topics from "./user_topics";
|
|
import * as util from "./util";
|
|
|
|
const max_topics = 8;
|
|
const max_topics_with_unread = 12;
|
|
|
|
function choose_topics(stream_id, topic_names, zoomed, topic_choice_state) {
|
|
for (const [idx, topic_name] of topic_names.entries()) {
|
|
const num_unread = unread.num_unread_for_topic(stream_id, topic_name);
|
|
const is_active_topic = topic_choice_state.active_topic === topic_name.toLowerCase();
|
|
const is_topic_muted = user_topics.is_topic_muted(stream_id, topic_name);
|
|
const is_topic_unmuted = user_topics.is_topic_unmuted(stream_id, topic_name);
|
|
const [topic_resolved_prefix, topic_display_name] =
|
|
resolved_topic.display_parts(topic_name);
|
|
// Important: Topics are lower-case in this set.
|
|
const contains_unread_mention = topic_choice_state.topics_with_unread_mentions.has(
|
|
topic_name.toLowerCase(),
|
|
);
|
|
|
|
if (!zoomed) {
|
|
function should_show_topic(topics_selected) {
|
|
// This function exists just for readability, to
|
|
// avoid long chained conditionals to determine
|
|
// which topics to include.
|
|
|
|
// We always show the active topic. Ideally, this
|
|
// logic would first check whether the active
|
|
// topic is in the set of those with unreads to
|
|
// avoid ending up with max_topics_with_unread + 1
|
|
// total topics if the active topic comes after
|
|
// the first several topics with unread messages.
|
|
if (is_active_topic) {
|
|
return true;
|
|
}
|
|
|
|
// We unconditionally skip showing muted topics
|
|
// when not zoomed, even if they have unread
|
|
// messages.
|
|
if (is_topic_muted) {
|
|
return false;
|
|
}
|
|
|
|
// We include the most recent max_topics topics,
|
|
// even if there are no unread messages.
|
|
if (idx < max_topics && topics_selected < max_topics) {
|
|
return true;
|
|
}
|
|
|
|
// We include older topics with unread messages up
|
|
// until max_topics_with_unread total topics have
|
|
// been included.
|
|
if (num_unread > 0 && topics_selected < max_topics_with_unread) {
|
|
return true;
|
|
}
|
|
|
|
// Otherwise, we don't show the topic in the
|
|
// unzoomed view. We might display its unread
|
|
// count in in "more topics" if it is not muted.
|
|
return false;
|
|
}
|
|
|
|
const show_topic = should_show_topic(topic_choice_state.topics_selected);
|
|
if (!show_topic) {
|
|
if (!is_topic_muted) {
|
|
topic_choice_state.more_topics_unmuted_unreads += num_unread;
|
|
if (contains_unread_mention) {
|
|
topic_choice_state.more_topics_have_unread_mention_messages = true;
|
|
}
|
|
} else {
|
|
topic_choice_state.more_topics_muted_unreads += num_unread;
|
|
if (contains_unread_mention) {
|
|
topic_choice_state.more_topics_have_muted_unread_mention_messages = true;
|
|
}
|
|
}
|
|
continue;
|
|
}
|
|
topic_choice_state.topics_selected += 1;
|
|
// We fall through to rendering the topic, using the
|
|
// same code we do when zoomed.
|
|
}
|
|
|
|
const topic_info = {
|
|
topic_name,
|
|
topic_resolved_prefix,
|
|
topic_display_name,
|
|
unread: num_unread,
|
|
is_zero: num_unread === 0,
|
|
is_muted: is_topic_muted,
|
|
is_unmuted: is_topic_unmuted,
|
|
is_active_topic,
|
|
url: hash_util.by_stream_topic_url(stream_id, topic_name),
|
|
contains_unread_mention,
|
|
};
|
|
|
|
topic_choice_state.items.push(topic_info);
|
|
}
|
|
}
|
|
|
|
export function get_list_info(stream_id, zoomed, search_term) {
|
|
const topic_choice_state = {
|
|
items: [],
|
|
topics_selected: 0,
|
|
more_topics_muted_unreads: 0,
|
|
more_topics_unmuted_unreads: 0,
|
|
more_topics_have_unread_mention_messages: false,
|
|
more_topics_have_muted_unread_mention_messages: false,
|
|
active_topic: narrow_state.topic()?.toLowerCase(),
|
|
topics_with_unread_mentions: unread.get_topics_with_unread_mentions(stream_id),
|
|
};
|
|
|
|
const stream_muted = sub_store.get(stream_id).is_muted;
|
|
|
|
let topic_names = stream_topic_history.get_recent_topic_names(stream_id);
|
|
if (zoomed) {
|
|
topic_names = util.filter_by_word_prefix_match(topic_names, search_term, (item) => item);
|
|
}
|
|
|
|
if (stream_muted && !zoomed) {
|
|
const unmuted_topics = topic_names.filter((topic) =>
|
|
user_topics.is_topic_unmuted(stream_id, topic),
|
|
);
|
|
choose_topics(stream_id, unmuted_topics, zoomed, topic_choice_state);
|
|
|
|
const other_topics = topic_names.filter(
|
|
(topic) => !user_topics.is_topic_unmuted(stream_id, topic),
|
|
);
|
|
choose_topics(stream_id, other_topics, zoomed, topic_choice_state);
|
|
} else {
|
|
choose_topics(stream_id, topic_names, zoomed, topic_choice_state);
|
|
}
|
|
|
|
if (
|
|
topic_choice_state.more_topics_unmuted_unreads === 0 &&
|
|
topic_choice_state.more_topics_muted_unreads > 0 &&
|
|
stream_muted
|
|
) {
|
|
// For muted streams, if the only unreads are in muted topics,
|
|
// we have a muted styling "more topics" row.
|
|
return {
|
|
items: topic_choice_state.items,
|
|
num_possible_topics: topic_names.length,
|
|
more_topics_unreads: topic_choice_state.more_topics_muted_unreads,
|
|
more_topics_have_unread_mention_messages:
|
|
topic_choice_state.more_topics_have_muted_unread_mention_messages,
|
|
more_topics_unread_count_muted: true,
|
|
};
|
|
}
|
|
return {
|
|
items: topic_choice_state.items,
|
|
num_possible_topics: topic_names.length,
|
|
more_topics_unreads: topic_choice_state.more_topics_unmuted_unreads,
|
|
more_topics_have_unread_mention_messages:
|
|
// Because mentions are important, and get displayed in the
|
|
// overall summary, we display the mention indicator even if
|
|
// they are in muted streams.
|
|
topic_choice_state.more_topics_have_unread_mention_messages ||
|
|
topic_choice_state.more_topics_have_muted_unread_mention_messages,
|
|
more_topics_unread_count_muted: false,
|
|
};
|
|
}
|