2016-10-27 01:02:41 +02:00
|
|
|
var topic_list = (function () {
|
|
|
|
|
|
|
|
var exports = {};
|
|
|
|
|
2016-11-10 15:35:14 +01:00
|
|
|
// We can only ever have one active widget.
|
|
|
|
var active_widget;
|
2016-10-27 01:36:20 +02:00
|
|
|
|
2016-11-10 16:15:12 +01:00
|
|
|
// We know whether we're zoomed or not.
|
|
|
|
var zoomed = false;
|
|
|
|
|
2016-10-27 01:53:47 +02:00
|
|
|
exports.remove_expanded_topics = function () {
|
2017-03-05 17:28:40 +01:00
|
|
|
stream_popover.hide_topic_popover();
|
2016-10-27 01:53:47 +02:00
|
|
|
|
2016-11-10 15:35:14 +01:00
|
|
|
if (active_widget) {
|
|
|
|
active_widget.remove();
|
|
|
|
}
|
|
|
|
};
|
2016-10-27 01:36:20 +02:00
|
|
|
|
2016-11-12 01:01:20 +01:00
|
|
|
function update_unread_count(unread_count_elem, count) {
|
|
|
|
// unread_count_elem is a jquery element...we expect DOM
|
|
|
|
// to look like this:
|
2016-11-12 01:14:34 +01:00
|
|
|
// <div class="topic-unread-count {{#if is_zero}}zero_count{{/if}}">
|
2016-11-12 01:01:20 +01:00
|
|
|
// <div class="value">{{unread}}</div>
|
|
|
|
// </div>
|
|
|
|
var value_span = unread_count_elem.find('.value');
|
|
|
|
|
|
|
|
if (value_span.length === 0) {
|
|
|
|
blueslip.error('malformed dom for unread count');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-10-27 01:02:41 +02:00
|
|
|
if (count === 0) {
|
2016-11-12 01:01:20 +01:00
|
|
|
unread_count_elem.hide();
|
2016-10-27 01:02:41 +02:00
|
|
|
value_span.text('');
|
|
|
|
} else {
|
2016-11-12 01:01:20 +01:00
|
|
|
unread_count_elem.removeClass("zero_count");
|
|
|
|
unread_count_elem.show();
|
2016-10-27 01:02:41 +02:00
|
|
|
value_span.text(count);
|
|
|
|
}
|
2016-10-29 19:39:47 +02:00
|
|
|
}
|
|
|
|
|
2017-05-13 19:26:54 +02:00
|
|
|
exports.set_count = function (stream_id, topic, count) {
|
|
|
|
if (active_widget && active_widget.is_for_stream(stream_id)) {
|
2016-11-10 15:35:14 +01:00
|
|
|
active_widget.set_count(topic, count);
|
2016-10-27 01:36:20 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2016-11-10 20:05:14 +01:00
|
|
|
exports.build_widget = function (parent_elem, stream, active_topic, max_topics) {
|
2016-10-29 20:19:25 +02:00
|
|
|
var self = {};
|
2016-10-29 20:42:13 +02:00
|
|
|
self.topic_items = new Dict({fold_case: true});
|
2016-10-27 02:02:40 +02:00
|
|
|
|
2017-05-13 19:26:54 +02:00
|
|
|
var my_stream_id = stream_data.get_stream_id(stream);
|
|
|
|
|
|
|
|
if (!my_stream_id) {
|
|
|
|
blueslip.error('Cannot find stream for ' + stream);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-10-29 20:19:25 +02:00
|
|
|
function build_list(stream, active_topic, max_topics) {
|
2017-05-14 17:38:07 +02:00
|
|
|
var topics = stream_data.get_recent_topics_for_id(my_stream_id) || [];
|
2016-10-27 02:02:40 +02:00
|
|
|
|
2016-10-29 20:19:25 +02:00
|
|
|
if (active_topic) {
|
|
|
|
active_topic = active_topic.toLowerCase();
|
2016-10-27 02:02:40 +02:00
|
|
|
}
|
|
|
|
|
2016-10-29 20:19:25 +02:00
|
|
|
var hiding_topics = false;
|
|
|
|
|
2016-11-05 19:34:47 +01:00
|
|
|
var ul = $('<ul class="topic-list">');
|
2016-10-29 20:19:25 +02:00
|
|
|
ul.attr('data-stream', stream);
|
|
|
|
|
|
|
|
_.each(topics, function (subject_obj, idx) {
|
2016-11-10 20:46:01 +01:00
|
|
|
var show_topic;
|
2016-10-29 20:19:25 +02:00
|
|
|
var topic_name = subject_obj.subject;
|
2017-05-13 19:26:54 +02:00
|
|
|
var num_unread = unread.num_unread_for_subject(my_stream_id, subject_obj.canon_subject);
|
2016-10-29 20:19:25 +02:00
|
|
|
|
2016-11-10 20:46:01 +01:00
|
|
|
if (zoomed) {
|
|
|
|
show_topic = true;
|
|
|
|
} else {
|
|
|
|
// Show the most recent topics, as well as any with unread messages
|
|
|
|
show_topic = (idx < max_topics) || (num_unread > 0) ||
|
2016-11-16 20:18:07 +01:00
|
|
|
(active_topic === topic_name.toLowerCase());
|
2016-11-10 20:46:01 +01:00
|
|
|
|
|
|
|
if (!show_topic) {
|
|
|
|
hiding_topics = true;
|
|
|
|
return;
|
|
|
|
}
|
2016-10-29 20:19:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
var topic_info = {
|
|
|
|
topic_name: topic_name,
|
|
|
|
unread: num_unread,
|
|
|
|
is_zero: num_unread === 0,
|
|
|
|
is_muted: muting.is_topic_muted(stream, topic_name),
|
2017-01-12 00:17:43 +01:00
|
|
|
url: narrow.by_stream_subject_uri(stream, topic_name),
|
2016-10-29 20:19:25 +02:00
|
|
|
};
|
2016-10-29 20:42:13 +02:00
|
|
|
var li = $(templates.render('topic_list_item', topic_info));
|
|
|
|
self.topic_items.set(topic_name, li);
|
2016-10-29 20:19:25 +02:00
|
|
|
ul.append(li);
|
|
|
|
});
|
|
|
|
|
|
|
|
if (hiding_topics) {
|
|
|
|
var show_more = $('<li class="show-more-topics">');
|
|
|
|
show_more.attr('data-stream', stream);
|
|
|
|
var link = $('<a href="#">');
|
|
|
|
link.html(i18n.t('more topics'));
|
|
|
|
show_more.html(link);
|
|
|
|
ul.append(show_more);
|
|
|
|
}
|
2016-10-27 02:02:40 +02:00
|
|
|
|
2016-10-29 20:19:25 +02:00
|
|
|
return ul;
|
2016-10-29 18:11:01 +02:00
|
|
|
}
|
2016-10-27 02:02:40 +02:00
|
|
|
|
2016-11-10 20:05:14 +01:00
|
|
|
self.get_parent = function () {
|
|
|
|
return parent_elem;
|
|
|
|
};
|
|
|
|
|
2017-05-13 19:26:54 +02:00
|
|
|
self.is_for_stream = function (stream_id) {
|
|
|
|
return stream_id === my_stream_id;
|
2016-11-10 15:35:14 +01:00
|
|
|
};
|
|
|
|
|
2016-11-10 20:19:22 +01:00
|
|
|
self.get_stream_name = function () {
|
|
|
|
return stream;
|
|
|
|
};
|
|
|
|
|
2016-10-29 20:19:25 +02:00
|
|
|
self.get_dom = function () {
|
|
|
|
return self.dom;
|
|
|
|
};
|
|
|
|
|
2016-11-10 15:35:14 +01:00
|
|
|
self.remove = function () {
|
|
|
|
self.dom.remove();
|
|
|
|
};
|
|
|
|
|
2016-10-29 21:01:07 +02:00
|
|
|
self.set_count = function (topic, count) {
|
|
|
|
if (!self.topic_items.has(topic)) {
|
2016-11-16 19:36:23 +01:00
|
|
|
// This can happen for truncated topic lists. No need
|
|
|
|
// to warn about it.
|
2016-10-29 21:01:07 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
var topic_li = self.topic_items.get(topic);
|
2016-11-12 01:14:34 +01:00
|
|
|
var unread_count_elem = topic_li.find('.topic-unread-count').expectOne();
|
2016-10-29 21:01:07 +02:00
|
|
|
|
2016-11-12 01:01:20 +01:00
|
|
|
update_unread_count(unread_count_elem, count);
|
2016-10-29 21:01:07 +02:00
|
|
|
};
|
|
|
|
|
2016-10-29 20:42:13 +02:00
|
|
|
self.activate_topic = function (active_topic) {
|
|
|
|
var li = self.topic_items.get(active_topic);
|
|
|
|
if (li) {
|
|
|
|
li.addClass('active-sub-filter');
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2016-10-29 20:19:25 +02:00
|
|
|
self.dom = build_list(stream, active_topic, max_topics);
|
2016-10-29 21:01:07 +02:00
|
|
|
|
2016-11-10 20:05:14 +01:00
|
|
|
parent_elem.append(self.dom);
|
|
|
|
|
|
|
|
if (active_topic) {
|
|
|
|
self.activate_topic(active_topic);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-10-29 20:19:25 +02:00
|
|
|
return self;
|
2016-10-27 02:02:40 +02:00
|
|
|
};
|
|
|
|
|
2016-11-10 19:24:20 +01:00
|
|
|
exports.rebuild = function (stream_li, stream) {
|
2016-10-27 02:33:24 +02:00
|
|
|
var max_topics = 5;
|
|
|
|
|
2017-04-25 15:25:31 +02:00
|
|
|
var active_topic = narrow_state.topic();
|
2016-10-27 02:33:24 +02:00
|
|
|
exports.remove_expanded_topics();
|
2016-11-10 20:05:14 +01:00
|
|
|
active_widget = exports.build_widget(stream_li, stream, active_topic, max_topics);
|
2016-10-27 02:33:24 +02:00
|
|
|
};
|
|
|
|
|
2016-11-10 16:15:12 +01:00
|
|
|
// For zooming, we only do topic-list stuff here...let stream_list
|
|
|
|
// handle hiding/showing the non-narrowed streams
|
|
|
|
exports.zoom_in = function () {
|
|
|
|
zoomed = true;
|
2016-11-10 20:46:01 +01:00
|
|
|
|
|
|
|
if (!active_widget) {
|
|
|
|
blueslip.error('Cannot find widget for topic history zooming.');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
exports.rebuild(active_widget.get_parent(), active_widget.get_stream_name());
|
2017-04-07 02:56:33 +02:00
|
|
|
$('#stream-filters-container').scrollTop(0);
|
|
|
|
$('#stream-filters-container').perfectScrollbar('update');
|
2016-11-10 16:15:12 +01:00
|
|
|
};
|
|
|
|
|
2016-11-10 16:45:56 +01:00
|
|
|
exports.zoom_out = function (options) {
|
2016-11-10 16:15:12 +01:00
|
|
|
zoomed = false;
|
2016-11-10 16:45:56 +01:00
|
|
|
if (options && options.clear_topics) {
|
|
|
|
exports.remove_expanded_topics();
|
2016-11-10 20:46:01 +01:00
|
|
|
} else {
|
|
|
|
exports.rebuild(active_widget.get_parent(), active_widget.get_stream_name());
|
2016-11-10 16:45:56 +01:00
|
|
|
}
|
2016-11-10 16:15:12 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
exports.is_zoomed = function () {
|
|
|
|
return zoomed;
|
|
|
|
};
|
|
|
|
|
2016-10-27 03:47:05 +02:00
|
|
|
exports.set_click_handlers = function (callbacks) {
|
|
|
|
$('#stream_filters').on('click', '.show-more-topics', function (e) {
|
|
|
|
callbacks.zoom_in();
|
|
|
|
|
|
|
|
e.preventDefault();
|
|
|
|
e.stopPropagation();
|
|
|
|
});
|
|
|
|
|
|
|
|
$('.show-all-streams').on('click', function (e) {
|
2016-11-10 16:45:56 +01:00
|
|
|
callbacks.zoom_out({clear_topics: false});
|
2016-10-27 03:47:05 +02:00
|
|
|
|
|
|
|
e.preventDefault();
|
|
|
|
e.stopPropagation();
|
|
|
|
});
|
|
|
|
|
2016-11-05 20:13:36 +01:00
|
|
|
$('#stream_filters').on('click', '.topic-box', function (e) {
|
2016-10-27 03:47:05 +02:00
|
|
|
if (e.metaKey || e.ctrlKey) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// In a more componentized world, we would delegate some
|
|
|
|
// of this stuff back up to our parents.
|
2017-05-06 02:40:32 +02:00
|
|
|
if (modals.is_active()) {
|
2017-03-18 21:35:35 +01:00
|
|
|
ui_util.change_tab_to('#home');
|
2016-10-27 03:47:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
var stream = $(e.target).parents('ul').attr('data-stream');
|
|
|
|
var topic = $(e.target).parents('li').attr('data-name');
|
|
|
|
|
|
|
|
narrow.activate([{operator: 'stream', operand: stream},
|
|
|
|
{operator: 'topic', operand: topic}],
|
|
|
|
{select_first_unread: true, trigger: 'sidebar'});
|
|
|
|
|
|
|
|
e.preventDefault();
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2016-10-27 01:36:20 +02:00
|
|
|
|
2016-10-27 01:02:41 +02:00
|
|
|
return exports;
|
|
|
|
}());
|
|
|
|
if (typeof module !== 'undefined') {
|
|
|
|
module.exports = topic_list;
|
|
|
|
}
|