const render_more_topics = require('../templates/more_topics.hbs'); const render_topic_list_item = require('../templates/topic_list_item.hbs'); const Dict = require('./dict').Dict; const FoldDict = require('./fold_dict').FoldDict; /* Track all active widgets with a Dict. (We have at max one for now, but we may eventually allow multiple streams to be expanded.) */ const active_widgets = new Dict(); // We know whether we're zoomed or not. let zoomed = false; exports.remove_expanded_topics = function () { stream_popover.hide_topic_popover(); _.each(active_widgets.values(), function (widget) { widget.remove(); }); active_widgets.clear(); }; exports.close = function () { zoomed = false; exports.remove_expanded_topics(); }; exports.zoom_out = function () { zoomed = false; const stream_ids = active_widgets.keys(); if (stream_ids.length !== 1) { blueslip.error('Unexpected number of topic lists to zoom out.'); return; } const stream_id = stream_ids[0]; const widget = active_widgets.get(stream_id); const parent_widget = widget.get_parent(); exports.rebuild(parent_widget, stream_id); }; function update_unread_count(unread_count_elem, count) { // unread_count_elem is a jquery element...we expect DOM // to look like this: //
//
{{unread}}
//
const value_span = unread_count_elem.find('.value'); if (value_span.length === 0) { blueslip.error('malformed dom for unread count'); return; } if (count === 0) { unread_count_elem.addClass("zero_count"); value_span.text(''); } else { unread_count_elem.removeClass("zero_count"); unread_count_elem.show(); value_span.text(count); } } exports.set_count = function (stream_id, topic, count) { const widget = active_widgets.get(stream_id); if (widget === undefined) { return false; } return widget.set_count(topic, count); }; exports.widget = function (parent_elem, my_stream_id) { const self = {}; const max_topics = 5; self.get_list_info = function () { let topics_selected = 0; let more_topics_unreads = 0; let active_topic = narrow_state.topic(); if (active_topic) { active_topic = active_topic.toLowerCase(); } const max_topics_with_unread = 8; const topic_names = topic_data.get_recent_names(my_stream_id); const items = []; _.each(topic_names, function (topic_name, idx) { const num_unread = unread.num_unread_for_topic(my_stream_id, topic_name); const is_active_topic = active_topic === topic_name.toLowerCase(); const is_topic_muted = muting.is_topic_muted(my_stream_id, topic_name); if (!zoomed) { function should_show_topic() { // 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) { 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(); if (!show_topic) { if (!is_topic_muted) { // The "more topics" unread count, like // stream-level counts, only counts messages // on unmuted topics. more_topics_unreads += num_unread; } return; } topics_selected += 1; // We fall through to rendering the topic, using the // same code we do when zoomed. } const topic_info = { topic_name: topic_name, unread: num_unread, is_zero: num_unread === 0, is_muted: is_topic_muted, is_active_topic: is_active_topic, url: hash_util.by_stream_topic_uri(my_stream_id, topic_name), }; items.push(topic_info); }); return { items: items, num_possible_topics: topic_names.length, more_topics_unreads: more_topics_unreads, }; }; self.build_list = function () { const list_info = self.get_list_info(); const num_possible_topics = list_info.num_possible_topics; const more_topics_unreads = list_info.more_topics_unreads; const ul = $('