mirror of
https://github.com/zulip/zulip.git
synced 2025-11-07 23:43:43 +00:00
This refactoring basically splits off two functions from update_unread_counts(), which then becomes a simple three-liner. The function get_unread_counts() is extracted, and it's purely functional computation. It paves the way for a more pull-based approach to getting "unread" counts, where other parts of the program can just call it to get values as needed without worrying about side effects. It is staying in zephyr.js for now. The other function is stream_list.update_dom_with_unread_counts(), which has a new home in stream_list.js. It handles all the DOM manipulation aspect of unread counts in the left pane, mostly by delegating to smaller functions within stream_list. Some of those smaller functions can now be turned into private methods FWIW, but I'm not sure it's worth the trouble. (imported from commit 799f9ebbaed8d530829a4741ef14be04bd8abf5a)
286 lines
9.3 KiB
JavaScript
286 lines
9.3 KiB
JavaScript
var stream_list = (function () {
|
|
|
|
var exports = {};
|
|
|
|
var previous_sort_order;
|
|
exports.sort_narrow_list = function () {
|
|
var streams = subs.subscribed_streams();
|
|
if (streams.length === 0) {
|
|
return;
|
|
}
|
|
|
|
var sort_recent = (streams.length > 40);
|
|
|
|
streams.sort(function(a, b) {
|
|
if (sort_recent) {
|
|
if (recent_subjects[b] !== undefined &&
|
|
recent_subjects[a] === undefined) {
|
|
return 1;
|
|
} else if (recent_subjects[b] === undefined &&
|
|
recent_subjects[a] !== undefined) {
|
|
return -1;
|
|
}
|
|
}
|
|
return util.strcmp(a, b);
|
|
});
|
|
|
|
if (previous_sort_order !== undefined
|
|
&& util.array_compare(previous_sort_order, streams)) {
|
|
return;
|
|
}
|
|
|
|
previous_sort_order = streams;
|
|
|
|
var parent = $('#stream_filters');
|
|
parent.empty();
|
|
|
|
var elems = [];
|
|
$.each(streams, function(i, stream) {
|
|
// TODO: we should export the sub objects better
|
|
var li = $(subs.have(stream).sidebar_li);
|
|
if (sort_recent) {
|
|
if (recent_subjects[stream] === undefined) {
|
|
li.addClass('inactive_stream');
|
|
} else {
|
|
li.removeClass('inactive_stream');
|
|
}
|
|
}
|
|
elems.push(li.get(0));
|
|
});
|
|
$(elems).appendTo(parent);
|
|
};
|
|
|
|
function iterate_to_find(selector, data_name, context) {
|
|
var retval = $();
|
|
$(selector, context).each(function (idx, elem) {
|
|
var jelem = $(elem);
|
|
if (jelem.attr('data-name') === data_name) {
|
|
retval = jelem;
|
|
return false;
|
|
}
|
|
});
|
|
return retval;
|
|
}
|
|
|
|
function get_filter_li(type, name) {
|
|
if (type === 'stream') {
|
|
return $("#stream_sidebar_" + subs.stream_id(name));
|
|
}
|
|
return iterate_to_find("#" + type + "_filters > li", name);
|
|
}
|
|
|
|
function get_subject_filter_li(stream, subject) {
|
|
var stream_li = get_filter_li('stream', stream);
|
|
return iterate_to_find(".expanded_subjects li", subject, stream_li);
|
|
}
|
|
|
|
function add_narrow_filter(name, type) {
|
|
var uri = "#narrow/stream/" + hashchange.encodeHashComponent(name);
|
|
var list_item;
|
|
|
|
if (get_filter_li(type, name).length) {
|
|
// already exists
|
|
return false;
|
|
}
|
|
|
|
// For some reason, even though the span is inline-block, if it is empty it
|
|
// takes up no space and you don't see the background color. Thus, add a
|
|
// to get the inline-block behavior we want.
|
|
var swatch = $('<span/>').attr('id', "stream_sidebar_swatch_" + subs.stream_id(name))
|
|
.addClass('streamlist_swatch')
|
|
.css('background-color', subs.get_color(name)).html(" ");
|
|
list_item = $('<li>').attr('data-name', name).html(swatch);
|
|
if (type === 'stream') {
|
|
list_item.attr('id', "stream_sidebar_" + subs.stream_id(name));
|
|
}
|
|
|
|
list_item.append($('<a>').attr('href', uri)
|
|
.addClass('subscription_name')
|
|
.text(name)
|
|
.append('<span class="count">(<span class="value"></span>)</span>'));
|
|
if (type === "stream" && subs.have(name).invite_only) {
|
|
list_item.append("<i class='icon-lock'/>");
|
|
}
|
|
$("#" + type + "_filters").append(list_item);
|
|
return list_item;
|
|
}
|
|
|
|
exports.get_count = function (type, name) {
|
|
return get_filter_li(type, name).find('.count .value').text();
|
|
};
|
|
|
|
function set_count_internal(count_span, value_span, count, clear_func) {
|
|
if (count === 0) {
|
|
return clear_func();
|
|
}
|
|
|
|
count_span.show();
|
|
|
|
value_span.text(count);
|
|
}
|
|
|
|
exports.set_count = function (type, name, count) {
|
|
var count_span = get_filter_li(type, name).find('.count');
|
|
var value_span = count_span.find('.value');
|
|
|
|
set_count_internal(count_span, value_span, count, function () { return exports.clear_count(type, name); });
|
|
};
|
|
|
|
exports.set_subject_count = function (stream, subject, count) {
|
|
var count_span = get_subject_filter_li(stream, subject).find('.subject_count');
|
|
var value_span = count_span.find('.value');
|
|
|
|
if (count_span.length === 0 || value_span.length === 0) {
|
|
return;
|
|
}
|
|
|
|
set_count_internal(count_span, value_span, count, function () {
|
|
get_subject_filter_li(stream, subject).find('.subject_count').hide()
|
|
.find('.value').text('');
|
|
});
|
|
};
|
|
|
|
exports.clear_count = function (type, name) {
|
|
get_filter_li(type, name).find('.count').hide()
|
|
.find('.value').text('');
|
|
};
|
|
|
|
exports.remove_narrow_filter = function (name, type) {
|
|
get_filter_li(type, name).remove();
|
|
};
|
|
|
|
exports.remove_all_narrow_filters = function () {
|
|
$("#stream_filters").children().remove();
|
|
};
|
|
|
|
function rebuild_recent_subjects(stream, subject) {
|
|
$('.expanded_subjects').remove();
|
|
var stream_li = get_filter_li('stream', stream);
|
|
var subjects = recent_subjects[stream] || [];
|
|
$.each(subjects, function (idx, subject_obj) {
|
|
var unread = 0;
|
|
if (unread_subjects[stream] !== undefined &&
|
|
unread_subjects[stream][subject_obj.subject] !== undefined) {
|
|
unread = Object.keys(unread_subjects[stream][subject_obj.subject]).length;
|
|
}
|
|
|
|
subject_obj.unread = unread;
|
|
subject_obj.has_unread = unread !== 0;
|
|
});
|
|
|
|
stream_li.append(templates.render('sidebar_subject_list',
|
|
{subjects: subjects,
|
|
stream: stream}));
|
|
if (subject !== undefined) {
|
|
get_subject_filter_li(stream, subject).addClass('active-subject-filter');
|
|
}
|
|
}
|
|
|
|
exports.update_streams_sidebar = function () {
|
|
exports.sort_narrow_list();
|
|
|
|
if (! narrow.active()) {
|
|
return;
|
|
}
|
|
|
|
var op_stream = narrow.filter().operands('stream');
|
|
var op_subject = narrow.filter().operands('subject');
|
|
var subject;
|
|
if (op_stream.length !== 0) {
|
|
if (op_subject.length !== 0) {
|
|
subject = op_subject[0];
|
|
}
|
|
if (subs.have(op_stream[0])) {
|
|
rebuild_recent_subjects(op_stream[0], subject);
|
|
}
|
|
}
|
|
};
|
|
|
|
exports.update_dom_with_unread_counts = function (counts) {
|
|
// counts is just a data object that gets calculated elsewhere
|
|
// Our job is to update some DOM elements.
|
|
|
|
// counts.stream_count maps streams to counts
|
|
$.each(counts.stream_count, function(stream, count) {
|
|
exports.set_count("stream", stream, count);
|
|
});
|
|
|
|
// counts.subject_count maps streams to hashes of subjects to counts
|
|
$.each(counts.subject_count, function(stream, subject_hash) {
|
|
$.each(subject_hash, function(subject, count) {
|
|
exports.set_subject_count(stream, subject, count);
|
|
});
|
|
});
|
|
|
|
// integer counts
|
|
exports.set_count("global", "private-message", counts.private_message_count);
|
|
exports.set_count("global", "home", counts.home_unread_messages);
|
|
};
|
|
|
|
$(function () {
|
|
$(document).on('narrow_activated.zephyr', function (event) {
|
|
$("ul.filters li").removeClass('active-filter active-subject-filter');
|
|
|
|
// TODO: handle confused filters like "in:all stream:foo"
|
|
var op_in = event.filter.operands('in');
|
|
if (op_in.length !== 0) {
|
|
if (['all', 'home'].indexOf(op_in[0]) !== -1) {
|
|
$("#global_filters li[data-name='" + op_in[0] + "']").addClass('active-filter');
|
|
}
|
|
}
|
|
var op_is = event.filter.operands('is');
|
|
if (op_is.length !== 0) {
|
|
if (['private-message', 'starred'].indexOf(op_is[0]) !== -1) {
|
|
$("#global_filters li[data-name='" + op_is[0] + "']").addClass('active-filter');
|
|
}
|
|
}
|
|
var op_stream = event.filter.operands('stream');
|
|
if (op_stream.length !== 0 && subs.have(op_stream[0])) {
|
|
var stream_li = get_filter_li('stream', op_stream[0]);
|
|
var op_subject = event.filter.operands('subject');
|
|
var subject;
|
|
if (op_subject.length !== 0) {
|
|
subject = op_subject[0];
|
|
} else {
|
|
stream_li.addClass('active-filter');
|
|
}
|
|
rebuild_recent_subjects(op_stream[0], subject);
|
|
}
|
|
});
|
|
|
|
$(document).on('narrow_deactivated.zephyr', function (event) {
|
|
$("ul.filters li").removeClass('active-filter active-subject-filter');
|
|
$("ul.expanded_subjects").remove();
|
|
$("#global_filters li[data-name='home']").addClass('active-filter');
|
|
});
|
|
|
|
$(document).on('sub_obj_created.zephyr', function (event) {
|
|
if (event.sub.subscribed) {
|
|
var stream_name = event.sub.name;
|
|
var li = add_narrow_filter(stream_name, "stream");
|
|
if (li) {
|
|
event.sub.sidebar_li = li;
|
|
}
|
|
}
|
|
});
|
|
|
|
$(document).on('subscription_add_done.zephyr', function (event) {
|
|
var stream_name = event.sub.name;
|
|
var li = add_narrow_filter(stream_name, "stream");
|
|
if (li) {
|
|
event.sub.sidebar_li = li;
|
|
}
|
|
exports.sort_narrow_list();
|
|
});
|
|
|
|
$(document).on('subscription_remove_done.zephyr', function (event) {
|
|
var stream_name = event.sub.name;
|
|
exports.remove_narrow_filter(stream_name, 'stream');
|
|
// We need to make sure we resort if the removed sub gets added again
|
|
previous_sort_order = undefined;
|
|
});
|
|
});
|
|
|
|
return exports;
|
|
}());
|