mirror of
https://github.com/zulip/zulip.git
synced 2025-11-09 16:37:23 +00:00
@@ -50,6 +50,7 @@ test("get_list_info w/real stream_topic_history", ({override}) => {
|
|||||||
|
|
||||||
assert.deepEqual(empty_list_info, {
|
assert.deepEqual(empty_list_info, {
|
||||||
items: [],
|
items: [],
|
||||||
|
more_topics_have_unread_mention_messages: false,
|
||||||
more_topics_unreads: 0,
|
more_topics_unreads: 0,
|
||||||
num_possible_topics: 0,
|
num_possible_topics: 0,
|
||||||
});
|
});
|
||||||
@@ -77,9 +78,11 @@ test("get_list_info w/real stream_topic_history", ({override}) => {
|
|||||||
list_info = get_list_info();
|
list_info = get_list_info();
|
||||||
assert.equal(list_info.items.length, 5);
|
assert.equal(list_info.items.length, 5);
|
||||||
assert.equal(list_info.more_topics_unreads, 0);
|
assert.equal(list_info.more_topics_unreads, 0);
|
||||||
|
assert.equal(list_info.more_topics_have_unread_mention_messages, false);
|
||||||
assert.equal(list_info.num_possible_topics, 7);
|
assert.equal(list_info.num_possible_topics, 7);
|
||||||
|
|
||||||
assert.deepEqual(list_info.items[0], {
|
assert.deepEqual(list_info.items[0], {
|
||||||
|
contains_unread_mention: false,
|
||||||
is_active_topic: true,
|
is_active_topic: true,
|
||||||
is_muted: false,
|
is_muted: false,
|
||||||
is_zero: true,
|
is_zero: true,
|
||||||
@@ -91,6 +94,7 @@ test("get_list_info w/real stream_topic_history", ({override}) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
assert.deepEqual(list_info.items[1], {
|
assert.deepEqual(list_info.items[1], {
|
||||||
|
contains_unread_mention: false,
|
||||||
is_active_topic: false,
|
is_active_topic: false,
|
||||||
is_muted: false,
|
is_muted: false,
|
||||||
is_zero: true,
|
is_zero: true,
|
||||||
@@ -108,6 +112,7 @@ test("get_list_info w/real stream_topic_history", ({override}) => {
|
|||||||
list_info = get_list_info(zoomed);
|
list_info = get_list_info(zoomed);
|
||||||
assert.equal(list_info.items.length, 7);
|
assert.equal(list_info.items.length, 7);
|
||||||
assert.equal(list_info.more_topics_unreads, 0);
|
assert.equal(list_info.more_topics_unreads, 0);
|
||||||
|
assert.equal(list_info.more_topics_have_unread_mention_messages, false);
|
||||||
assert.equal(list_info.num_possible_topics, 7);
|
assert.equal(list_info.num_possible_topics, 7);
|
||||||
|
|
||||||
add_topic_message("After Brooklyn", 1008);
|
add_topic_message("After Brooklyn", 1008);
|
||||||
@@ -117,6 +122,7 @@ test("get_list_info w/real stream_topic_history", ({override}) => {
|
|||||||
list_info = get_list_info(zoomed);
|
list_info = get_list_info(zoomed);
|
||||||
assert.equal(list_info.items.length, 2);
|
assert.equal(list_info.items.length, 2);
|
||||||
assert.equal(list_info.more_topics_unreads, 0);
|
assert.equal(list_info.more_topics_unreads, 0);
|
||||||
|
assert.equal(list_info.more_topics_have_unread_mention_messages, false);
|
||||||
assert.equal(list_info.num_possible_topics, 2);
|
assert.equal(list_info.num_possible_topics, 2);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -144,6 +150,20 @@ test("get_list_info unreads", ({override}) => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function add_unreads_with_mention(topic, count) {
|
||||||
|
unread.process_loaded_messages(
|
||||||
|
Array.from({length: count}, () => ({
|
||||||
|
id: (message_id += 1),
|
||||||
|
stream_id: general.stream_id,
|
||||||
|
topic,
|
||||||
|
type: "stream",
|
||||||
|
unread: true,
|
||||||
|
mentioned: true,
|
||||||
|
mentioned_me_directly: true,
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We have 15 topics, but we only show up
|
We have 15 topics, but we only show up
|
||||||
to 8 topics, depending on how many have
|
to 8 topics, depending on how many have
|
||||||
@@ -156,9 +176,18 @@ test("get_list_info unreads", ({override}) => {
|
|||||||
add_unreads("topic 8", 8);
|
add_unreads("topic 8", 8);
|
||||||
add_unreads("topic 9", 9);
|
add_unreads("topic 9", 9);
|
||||||
|
|
||||||
|
/*
|
||||||
|
We added 9 unread messages in 'topic 9',
|
||||||
|
but now we would add a unread message
|
||||||
|
with `mention` for user, to test
|
||||||
|
`more_topics_have_unread_mention_messages`.
|
||||||
|
*/
|
||||||
|
add_unreads_with_mention("topic 9", 1);
|
||||||
|
|
||||||
list_info = get_list_info();
|
list_info = get_list_info();
|
||||||
assert.equal(list_info.items.length, 7);
|
assert.equal(list_info.items.length, 7);
|
||||||
assert.equal(list_info.more_topics_unreads, 0);
|
assert.equal(list_info.more_topics_unreads, 0);
|
||||||
|
assert.equal(list_info.more_topics_have_unread_mention_messages, false);
|
||||||
assert.equal(list_info.num_possible_topics, 15);
|
assert.equal(list_info.num_possible_topics, 15);
|
||||||
|
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
@@ -171,7 +200,8 @@ test("get_list_info unreads", ({override}) => {
|
|||||||
|
|
||||||
list_info = get_list_info();
|
list_info = get_list_info();
|
||||||
assert.equal(list_info.items.length, 8);
|
assert.equal(list_info.items.length, 8);
|
||||||
assert.equal(list_info.more_topics_unreads, 9);
|
assert.equal(list_info.more_topics_unreads, 10);
|
||||||
|
assert.equal(list_info.more_topics_have_unread_mention_messages, true);
|
||||||
assert.equal(list_info.num_possible_topics, 15);
|
assert.equal(list_info.num_possible_topics, 15);
|
||||||
|
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
@@ -190,7 +220,8 @@ test("get_list_info unreads", ({override}) => {
|
|||||||
|
|
||||||
list_info = get_list_info();
|
list_info = get_list_info();
|
||||||
assert.equal(list_info.items.length, 8);
|
assert.equal(list_info.items.length, 8);
|
||||||
assert.equal(list_info.more_topics_unreads, 9 + 13);
|
assert.equal(list_info.more_topics_unreads, 10 + 13);
|
||||||
|
assert.equal(list_info.more_topics_have_unread_mention_messages, true);
|
||||||
assert.equal(list_info.num_possible_topics, 15);
|
assert.equal(list_info.num_possible_topics, 15);
|
||||||
|
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
|
|||||||
@@ -627,6 +627,35 @@ test("stream_has_any_unread_mentions", () => {
|
|||||||
assert.equal(unread.stream_has_any_unread_mentions(muted_stream_id), false);
|
assert.equal(unread.stream_has_any_unread_mentions(muted_stream_id), false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("topics with unread mentions", () => {
|
||||||
|
const message_with_mention = {
|
||||||
|
id: 98,
|
||||||
|
type: "stream",
|
||||||
|
stream_id: 999,
|
||||||
|
topic: "topic with mention",
|
||||||
|
mentioned: true,
|
||||||
|
mentioned_me_directly: true,
|
||||||
|
unread: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
const message_without_mention = {
|
||||||
|
id: 99,
|
||||||
|
type: "stream",
|
||||||
|
stream_id: 999,
|
||||||
|
topic: "topic without mention",
|
||||||
|
mentioned: false,
|
||||||
|
mentioned_me_directly: false,
|
||||||
|
unread: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
unread.process_loaded_messages([message_with_mention, message_without_mention]);
|
||||||
|
assert.equal(unread.get_topics_with_unread_mentions(999).size, 1);
|
||||||
|
assert.deepEqual(unread.get_topics_with_unread_mentions(999), new Set(["topic with mention"]));
|
||||||
|
unread.mark_as_read(message_with_mention.id);
|
||||||
|
assert.equal(unread.get_topics_with_unread_mentions(999).size, 0);
|
||||||
|
assert.deepEqual(unread.get_topics_with_unread_mentions(999), new Set([]));
|
||||||
|
});
|
||||||
|
|
||||||
test("starring", () => {
|
test("starring", () => {
|
||||||
// We don't need any setup here, because we just hard code
|
// We don't need any setup here, because we just hard code
|
||||||
// this to [] in the code.
|
// this to [] in the code.
|
||||||
|
|||||||
@@ -82,10 +82,11 @@ export function keyed_topic_li(conversation) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function more_li(more_topics_unreads) {
|
export function more_li(more_topics_unreads, more_topics_have_unread_mention_messages) {
|
||||||
const render = () =>
|
const render = () =>
|
||||||
render_more_topics({
|
render_more_topics({
|
||||||
more_topics_unreads,
|
more_topics_unreads,
|
||||||
|
more_topics_have_unread_mention_messages,
|
||||||
});
|
});
|
||||||
|
|
||||||
const eq = (other) => other.more_items && more_topics_unreads === other.more_topics_unreads;
|
const eq = (other) => other.more_items && more_topics_unreads === other.more_topics_unreads;
|
||||||
@@ -142,6 +143,8 @@ export class TopicListWidget {
|
|||||||
|
|
||||||
const num_possible_topics = list_info.num_possible_topics;
|
const num_possible_topics = list_info.num_possible_topics;
|
||||||
const more_topics_unreads = list_info.more_topics_unreads;
|
const more_topics_unreads = list_info.more_topics_unreads;
|
||||||
|
const more_topics_have_unread_mention_messages =
|
||||||
|
list_info.more_topics_have_unread_mention_messages;
|
||||||
|
|
||||||
const is_showing_all_possible_topics =
|
const is_showing_all_possible_topics =
|
||||||
list_info.items.length === num_possible_topics &&
|
list_info.items.length === num_possible_topics &&
|
||||||
@@ -154,7 +157,7 @@ export class TopicListWidget {
|
|||||||
if (spinner) {
|
if (spinner) {
|
||||||
nodes.push(spinner_li());
|
nodes.push(spinner_li());
|
||||||
} else if (!is_showing_all_possible_topics) {
|
} else if (!is_showing_all_possible_topics) {
|
||||||
nodes.push(more_li(more_topics_unreads));
|
nodes.push(more_li(more_topics_unreads, more_topics_have_unread_mention_messages));
|
||||||
} else if (zoomed) {
|
} else if (zoomed) {
|
||||||
// In the zoomed topic view, we need to add the input
|
// In the zoomed topic view, we need to add the input
|
||||||
// for filtering through list of topics.
|
// for filtering through list of topics.
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ const max_topics_with_unread = 8;
|
|||||||
export function get_list_info(stream_id, zoomed) {
|
export function get_list_info(stream_id, zoomed) {
|
||||||
let topics_selected = 0;
|
let topics_selected = 0;
|
||||||
let more_topics_unreads = 0;
|
let more_topics_unreads = 0;
|
||||||
|
let more_topics_have_unread_mention_messages = false;
|
||||||
|
|
||||||
let active_topic = narrow_state.topic();
|
let active_topic = narrow_state.topic();
|
||||||
|
|
||||||
@@ -29,12 +30,16 @@ export function get_list_info(stream_id, zoomed) {
|
|||||||
|
|
||||||
const items = [];
|
const items = [];
|
||||||
|
|
||||||
|
const topics_with_unread_mentions = unread.get_topics_with_unread_mentions(stream_id);
|
||||||
|
|
||||||
for (const [idx, topic_name] of topic_names.entries()) {
|
for (const [idx, topic_name] of topic_names.entries()) {
|
||||||
const num_unread = unread.num_unread_for_topic(stream_id, topic_name);
|
const num_unread = unread.num_unread_for_topic(stream_id, topic_name);
|
||||||
const is_active_topic = active_topic === topic_name.toLowerCase();
|
const is_active_topic = active_topic === topic_name.toLowerCase();
|
||||||
const is_topic_muted = user_topics.is_topic_muted(stream_id, topic_name);
|
const is_topic_muted = user_topics.is_topic_muted(stream_id, topic_name);
|
||||||
const [topic_resolved_prefix, topic_display_name] =
|
const [topic_resolved_prefix, topic_display_name] =
|
||||||
resolved_topic.display_parts(topic_name);
|
resolved_topic.display_parts(topic_name);
|
||||||
|
// Important: Topics are lower-case in this set.
|
||||||
|
const contains_unread_mention = topics_with_unread_mentions.has(topic_name.toLowerCase());
|
||||||
|
|
||||||
if (!zoomed) {
|
if (!zoomed) {
|
||||||
function should_show_topic(topics_selected) {
|
function should_show_topic(topics_selected) {
|
||||||
@@ -85,6 +90,9 @@ export function get_list_info(stream_id, zoomed) {
|
|||||||
// stream-level counts, only counts messages
|
// stream-level counts, only counts messages
|
||||||
// on unmuted topics.
|
// on unmuted topics.
|
||||||
more_topics_unreads += num_unread;
|
more_topics_unreads += num_unread;
|
||||||
|
if (contains_unread_mention) {
|
||||||
|
more_topics_have_unread_mention_messages = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -102,6 +110,7 @@ export function get_list_info(stream_id, zoomed) {
|
|||||||
is_muted: is_topic_muted,
|
is_muted: is_topic_muted,
|
||||||
is_active_topic,
|
is_active_topic,
|
||||||
url: hash_util.by_stream_topic_url(stream_id, topic_name),
|
url: hash_util.by_stream_topic_url(stream_id, topic_name),
|
||||||
|
contains_unread_mention,
|
||||||
};
|
};
|
||||||
|
|
||||||
items.push(topic_info);
|
items.push(topic_info);
|
||||||
@@ -111,5 +120,6 @@ export function get_list_info(stream_id, zoomed) {
|
|||||||
items,
|
items,
|
||||||
num_possible_topics: topic_names.length,
|
num_possible_topics: topic_names.length,
|
||||||
more_topics_unreads,
|
more_topics_unreads,
|
||||||
|
more_topics_have_unread_mention_messages,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -404,6 +404,32 @@ class UnreadTopicCounter {
|
|||||||
|
|
||||||
return id_set.size !== 0;
|
return id_set.size !== 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get_topics_with_unread_mentions(stream_id) {
|
||||||
|
// Returns the set of lower cased topics with unread mentions
|
||||||
|
// in the given stream.
|
||||||
|
const result = new Set();
|
||||||
|
const per_stream_bucketer = this.bucketer.get_bucket(stream_id);
|
||||||
|
|
||||||
|
if (!per_stream_bucketer) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const message_id of unread_mentions_counter) {
|
||||||
|
// Because bucket keys in per_stream_bucketer are topics,
|
||||||
|
// we can just directly use reverse_lookup to find the
|
||||||
|
// topic in this stream containing a given unread message
|
||||||
|
// ID. If it's not in this stream, we'll get undefined.
|
||||||
|
const topic_match = per_stream_bucketer.reverse_lookup.get(message_id);
|
||||||
|
if (topic_match !== undefined) {
|
||||||
|
// Important: We lower-case topics here before adding them
|
||||||
|
// to this set, to support case-insensitive checks.
|
||||||
|
result.add(topic_match.toLowerCase());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const unread_topic_counter = new UnreadTopicCounter();
|
const unread_topic_counter = new UnreadTopicCounter();
|
||||||
|
|
||||||
@@ -601,6 +627,10 @@ export function topic_has_any_unread(stream_id, topic) {
|
|||||||
return unread_topic_counter.topic_has_any_unread(stream_id, topic);
|
return unread_topic_counter.topic_has_any_unread(stream_id, topic);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function get_topics_with_unread_mentions(stream_id) {
|
||||||
|
return unread_topic_counter.get_topics_with_unread_mentions(stream_id);
|
||||||
|
}
|
||||||
|
|
||||||
export function num_unread_for_person(user_ids_string) {
|
export function num_unread_for_person(user_ids_string) {
|
||||||
return unread_pm_counter.num_unread(user_ids_string);
|
return unread_pm_counter.num_unread(user_ids_string);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
<li class="topic-list-item show-more-topics bottom_left_row {{#unless more_topics_unreads}}zero-topic-unreads{{/unless}}">
|
<li class="topic-list-item show-more-topics bottom_left_row {{#unless more_topics_unreads}}zero-topic-unreads{{/unless}}">
|
||||||
<span class='topic-box'>
|
<span class='topic-box'>
|
||||||
<a class="topic-name" tabindex="0">{{t "more topics" }}</a>
|
<a class="topic-name" tabindex="0">{{t "more topics" }}</a>
|
||||||
|
{{#if more_topics_have_unread_mention_messages}}
|
||||||
|
<span class="unread_mention_info">
|
||||||
|
@
|
||||||
|
</span>
|
||||||
|
{{/if}}
|
||||||
<span class="unread_count {{#unless more_topics_unreads}}zero_count{{/unless}}">
|
<span class="unread_count {{#unless more_topics_unreads}}zero_count{{/unless}}">
|
||||||
{{more_topics_unreads}}
|
{{more_topics_unreads}}
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -6,6 +6,11 @@
|
|||||||
<a href='{{url}}' class="topic-name" title="{{topic_name}}">
|
<a href='{{url}}' class="topic-name" title="{{topic_name}}">
|
||||||
{{topic_display_name}}
|
{{topic_display_name}}
|
||||||
</a>
|
</a>
|
||||||
|
{{#if contains_unread_mention}}
|
||||||
|
<span class="unread_mention_info">
|
||||||
|
@
|
||||||
|
</span>
|
||||||
|
{{/if}}
|
||||||
<span class="unread_count {{#if is_zero}}zero_count{{/if}}">
|
<span class="unread_count {{#if is_zero}}zero_count{{/if}}">
|
||||||
{{unread}}
|
{{unread}}
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
Reference in New Issue
Block a user