diff --git a/static/js/narrow.js b/static/js/narrow.js index d7eaa51b97..0295783e44 100644 --- a/static/js/narrow.js +++ b/static/js/narrow.js @@ -324,7 +324,7 @@ exports.by_subject = function (target_id, opts) { exports.by_recipient(target_id, opts); return; } - mark_message_as_read(original); + unread.mark_message_as_read(original); opts = _.defaults({}, opts, {then_select_id: target_id}); exports.activate([ ['stream', original.stream], @@ -337,7 +337,7 @@ exports.by_recipient = function (target_id, opts) { opts = _.defaults({}, opts, {then_select_id: target_id}); // don't use current_msg_list as it won't work for muted messages or for out-of-narrow links var message = msg_metadata_cache[target_id]; - mark_message_as_read(message); + unread.mark_message_as_read(message); switch (message.type) { case 'private': exports.by('pm-with', message.reply_to, opts); diff --git a/static/js/navigate.js b/static/js/navigate.js index 57e9e89eb7..6fbdac3fca 100644 --- a/static/js/navigate.js +++ b/static/js/navigate.js @@ -31,7 +31,7 @@ exports.down = function (with_centering) { // always returns a message. var current_msg_table = rows.get_table(current_msg_list.table_name); viewport.scrollTop(current_msg_table.outerHeight(true) - viewport.height() * 0.1); - mark_current_list_as_read(); + unread.mark_current_list_as_read(); } }; @@ -48,7 +48,7 @@ exports.to_end = function () { last_viewport_movement_direction = 1; current_msg_list.select_id(next_id, {then_scroll: true, from_scroll: true}); - mark_current_list_as_read(); + unread.mark_current_list_as_read(); }; exports.page_up = function () { @@ -63,7 +63,7 @@ exports.page_up = function () { exports.page_down = function () { if (viewport.at_bottom() && !current_msg_list.empty()) { current_msg_list.select_id(current_msg_list.last().id, {then_scroll: false}); - mark_current_list_as_read(); + unread.mark_current_list_as_read(); } else { ui.page_down_the_right_amount(); diff --git a/static/js/notifications.js b/static/js/notifications.js index 10c02fe5b5..87902f7d01 100644 --- a/static/js/notifications.js +++ b/static/js/notifications.js @@ -45,7 +45,7 @@ exports.initialize = function () { // Update many places on the DOM to reflect unread // counts. - process_visible_unread_messages(); + unread.process_visible(); }).blur(function () { window_has_focus = false; diff --git a/static/js/server_events.js b/static/js/server_events.js index a02e6354eb..4cdaa6694b 100644 --- a/static/js/server_events.js +++ b/static/js/server_events.js @@ -125,7 +125,7 @@ function get_events_success(events) { var msgs_to_update = _.map(event.messages, function (message_id) { return msg_metadata_cache[message_id]; }); - mark_messages_as_read(msgs_to_update, {from: "server"}); + unread.mark_messages_as_read(msgs_to_update, {from: "server"}); break; } break; diff --git a/static/js/stream_list.js b/static/js/stream_list.js index af0931705f..1e6b4a4d9d 100644 --- a/static/js/stream_list.js +++ b/static/js/stream_list.js @@ -423,7 +423,7 @@ $(function () { stream_li.addClass('active-filter'); } rebuild_recent_subjects(op_stream[0], subject); - process_visible_unread_messages(); + unread.process_visible(); } var op_pm = event.filter.operands('pm-with'); if (op_pm.length === 1) { diff --git a/static/js/subs.js b/static/js/subs.js index 2940a40a1f..97c59524f7 100644 --- a/static/js/subs.js +++ b/static/js/subs.js @@ -105,7 +105,7 @@ function update_in_home_view(sub, value) { suppress_scroll_pointer_update = true; if (! home_msg_list.empty()) { - process_loaded_for_unread(home_msg_list.all()); + unread.process_loaded_messages(home_msg_list.all()); } }, 0); @@ -297,7 +297,7 @@ function mark_subscribed(stream_name, attrs) { // Update unread counts as the new stream in sidebar might // need its unread counts re-calculated - process_loaded_for_unread(all_msg_list.all()); + unread.process_loaded_messages(all_msg_list.all()); $(document).trigger($.Event('subscription_add_done.zulip', {sub: sub})); } diff --git a/static/js/ui.js b/static/js/ui.js index 25e1702da0..20168663c0 100644 --- a/static/js/ui.js +++ b/static/js/ui.js @@ -720,7 +720,7 @@ exports.update_starred = function (message_id, starred) { // lists. var message = find_message(message_id); - mark_message_as_read(message); + unread.mark_message_as_read(message); message.starred = starred; @@ -743,7 +743,7 @@ function toggle_star(message_id) { // lists. var message = find_message(message_id); - mark_message_as_read(message); + unread.mark_message_as_read(message); exports.update_starred(message.id, message.starred !== true); message_flags.send_starred([message], message.starred); } @@ -1712,7 +1712,7 @@ $(function () { }); $(".bankruptcy_button").click(function (e) { - enable_unread_counts(); + unread.enable(); }); $('#yes-bankrupt').click(function (e) { @@ -1769,9 +1769,9 @@ function scroll_finished() { } // When the window scrolls, it may cause some messages to // enter the screen and become read. Calling - // process_visible_unread_messages will update necessary + // unread.process_visible will update necessary // data structures and DOM elements. - setTimeout(process_visible_unread_messages, 0); + setTimeout(unread.process_visible, 0); } } @@ -1788,7 +1788,7 @@ var saved_compose_cursor = 0; $(function () { viewport.message_pane.scroll($.throttle(50, function (e) { - process_visible_unread_messages(); + unread.process_visible(); scroll_finish(); })); diff --git a/static/js/unread.js b/static/js/unread.js index 28452692b4..d0755e56f2 100644 --- a/static/js/unread.js +++ b/static/js/unread.js @@ -171,6 +171,105 @@ exports.num_unread_for_person = function (email) { return unread_privates.get(email).num_items(); }; +exports.update_unread_counts = function () { + if (suppress_unread_counts) { + return; + } + + // Pure computation: + var res = unread.get_counts(); + + // Side effects from here down: + // This updates some DOM elements directly, so try to + // avoid excessive calls to this. + stream_list.update_dom_with_unread_counts(res); + notifications.update_title_count(res.home_unread_messages); + notifications.update_pm_count(res.private_message_count); + notifications_bar.update(res.home_unread_messages); +}; + +exports.enable = function enable() { + suppress_unread_counts = false; + exports.update_unread_counts(); +}; + +exports.mark_all_as_read = function mark_all_as_read(cont) { + _.each(all_msg_list.all(), function (msg) { + msg.flags = msg.flags || []; + msg.flags.push('read'); + }); + unread.declare_bankruptcy(); + exports.update_unread_counts(); + + channel.post({ + url: '/json/update_message_flags', + idempotent: true, + data: {messages: JSON.stringify([]), + all: true, + op: 'add', + flag: 'read'}, + success: cont}); +}; + +// Takes a list of messages and marks them as read +exports.mark_messages_as_read = function mark_messages_as_read (messages, options) { + options = options || {}; + var processed = false; + + _.each(messages, function (message) { + if (!unread.message_unread(message)) { + // Don't do anything if the message is already read. + return; + } + if (current_msg_list === narrowed_msg_list) { + unread_messages_read_in_narrow = true; + } + + if (options.from !== "server") { + message_flags.send_read(message); + } + summary.maybe_mark_summarized(message); + + message.unread = false; + unread.process_read_message(message, options); + home_msg_list.show_message_as_read(message, options); + all_msg_list.show_message_as_read(message, options); + if (narrowed_msg_list) { + narrowed_msg_list.show_message_as_read(message, options); + } + notifications.close_notification(message); + processed = true; + }); + + if (processed) { + exports.update_unread_counts(); + } +}; + +exports.mark_message_as_read = function mark_message_as_read(message, options) { + exports.mark_messages_as_read([message], options); +}; + +// If we ever materially change the algorithm for this function, we +// may need to update notifications.received_messages as well. +exports.process_visible = function process_visible(update_cursor) { + if (! notifications.window_has_focus()) { + return; + } + + if (feature_flags.mark_read_at_bottom) { + if (viewport.bottom_message_visible()) { + exports.mark_current_list_as_read(); + } + } else { + exports.mark_messages_as_read(viewport.visible_messages(true)); + } +}; + +exports.mark_current_list_as_read = function mark_current_list_as_read(options) { + exports.mark_messages_as_read(current_msg_list.all(), options); +}; + return exports; }()); if (typeof module !== 'undefined') { diff --git a/static/js/zulip.js b/static/js/zulip.js index c660f831d8..6c7ac64221 100644 --- a/static/js/zulip.js +++ b/static/js/zulip.js @@ -204,113 +204,16 @@ function message_range(msg_list, start, end) { return all.slice(start_idx, end_idx + 1); } -function update_unread_counts() { - if (suppress_unread_counts) { - return; - } - - // Pure computation: - var res = unread.get_counts(); - - // Side effects from here down: - // This updates some DOM elements directly, so try to - // avoid excessive calls to this. - stream_list.update_dom_with_unread_counts(res); - notifications.update_title_count(res.home_unread_messages); - notifications.update_pm_count(res.private_message_count); - notifications_bar.update(res.home_unread_messages); -} - -function enable_unread_counts() { - suppress_unread_counts = false; - update_unread_counts(); -} - -function mark_all_as_read(cont) { - _.each(all_msg_list.all(), function (msg) { - msg.flags = msg.flags || []; - msg.flags.push('read'); - }); - unread.declare_bankruptcy(); - update_unread_counts(); - - channel.post({ - url: '/json/update_message_flags', - idempotent: true, - data: {messages: JSON.stringify([]), - all: true, - op: 'add', - flag: 'read'}, - success: cont}); -} - +// Moving this to unread.js is a little messy because there is already +// an unread.process_loaded_messages (which this calls) function process_loaded_for_unread(messages) { activity.process_loaded_messages(messages); activity.update_huddles(); unread.process_loaded_messages(messages); - update_unread_counts(); + unread.update_unread_counts(); ui.resize_page_components(); } -// Takes a list of messages and marks them as read -function mark_messages_as_read(messages, options) { - options = options || {}; - var processed = false; - - _.each(messages, function (message) { - if (!unread.message_unread(message)) { - // Don't do anything if the message is already read. - return; - } - if (current_msg_list === narrowed_msg_list) { - unread_messages_read_in_narrow = true; - } - - if (options.from !== "server") { - message_flags.send_read(message); - } - summary.maybe_mark_summarized(message); - - message.unread = false; - unread.process_read_message(message, options); - home_msg_list.show_message_as_read(message, options); - all_msg_list.show_message_as_read(message, options); - if (narrowed_msg_list) { - narrowed_msg_list.show_message_as_read(message, options); - } - notifications.close_notification(message); - processed = true; - }); - - if (processed) { - update_unread_counts(); - } -} - -function mark_message_as_read(message, options) { - mark_messages_as_read([message], options); -} - -// If we ever materially change the algorithm for this function, we -// may need to update notifications.received_messages as well. -function process_visible_unread_messages(update_cursor) { - if (! notifications.window_has_focus()) { - return; - } - - if (feature_flags.mark_read_at_bottom) { - if (viewport.bottom_message_visible()) { - mark_current_list_as_read(); - } - } else { - mark_messages_as_read(viewport.visible_messages(true)); - } -} - -function mark_current_list_as_read(options) { - mark_messages_as_read(current_msg_list.all(), options); -} - function respond_to_message(opts) { var message, msg_type; // Before initiating a reply to a message, if there's an @@ -323,7 +226,7 @@ function respond_to_message(opts) { return; } - mark_message_as_read(message); + unread.mark_message_as_read(message); var stream = ''; var subject = ''; @@ -588,7 +491,7 @@ function maybe_add_narrowed_messages(messages, msg_list, messages_are_new) { new_messages = _.map(new_messages, add_message_metadata); add_messages(new_messages, msg_list, {messages_are_new: messages_are_new}); - process_visible_unread_messages(); + unread.process_visible(); notifications.possibly_notify_new_messages_outside_viewport(new_messages); notifications.notify_messages_outside_current_search(elsewhere_messages); }, @@ -663,7 +566,7 @@ function update_messages(events) { if (current_msg_list === narrowed_msg_list) { narrowed_msg_list.rerender(); } - update_unread_counts(); + unread.update_unread_counts(); stream_list.update_streams_sidebar(); } @@ -679,7 +582,7 @@ function insert_new_messages(messages) { } // You must add add messages to home_msg_list BEFORE - // calling process_loaded_for_unread. + // calling unread.process_loaded_messages. add_messages(messages, home_msg_list, {messages_are_new: true}); add_messages(messages, all_msg_list, {messages_are_new: true}); @@ -695,7 +598,7 @@ function insert_new_messages(messages) { notifications.possibly_notify_new_messages_outside_viewport(messages); } - process_loaded_for_unread(messages); + unread.process_loaded_messages(messages); if (narrow.narrowed_by_reply()) { // If you send a message when narrowed to a recipient, move the @@ -720,7 +623,7 @@ function insert_new_messages(messages) { } } - process_visible_unread_messages(); + unread.process_visible(); notifications.received_messages(messages); stream_list.update_streams_sidebar(); } @@ -741,7 +644,7 @@ function process_result(messages, opts) { // the all_msg_list as well, as the home_msg_list is reconstructed // from all_msg_list. if (opts.msg_list === home_msg_list) { - process_loaded_for_unread(messages); + unread.process_loaded_messages(messages); add_messages(messages, all_msg_list, {messages_are_new: false}); } @@ -873,7 +776,7 @@ function fast_forward_pointer() { idempotent: true, data: {email: page_params.email}, success: function (data) { - mark_all_as_read(function () { + unread.mark_all_as_read(function () { furthest_read = data.max_message_id; unconditionally_send_pointer_update().then(function () { ui.change_tab_to('#home'); @@ -892,7 +795,7 @@ function consider_bankruptcy() { if (!page_params.furthest_read_time) { // We've never read a message. - enable_unread_counts(); + unread.enable(); return; } @@ -904,7 +807,7 @@ function consider_bankruptcy() { $('#bankruptcy-unread-count').html(unread_info); $('#bankruptcy').modal('show'); } else { - enable_unread_counts(); + unread.enable(); } } @@ -950,7 +853,7 @@ function main() { } else { messages = message_range(event.msg_list, event.previously_selected, event.id); } - mark_messages_as_read(messages, {from: 'pointer'}); + unread.mark_messages_as_read(messages, {from: 'pointer'}); } }); diff --git a/tools/jslint/check-all.js b/tools/jslint/check-all.js index f8a67d61ef..53f23f83e0 100644 --- a/tools/jslint/check-all.js +++ b/tools/jslint/check-all.js @@ -57,16 +57,15 @@ var globals = + ' keep_pointer_in_view unread_messages_read_in_narrow' + ' respond_to_message recenter_view last_viewport_movement_direction' + ' scroll_to_selected get_private_message_recipient' - + ' load_old_messages enable_unread_counts' - + ' process_visible_unread_messages mark_messages_as_read viewport ' + + ' load_old_messages ' + + ' viewport ' + ' load_more_messages reset_load_more_status have_scrolled_away_from_top' + ' maybe_scroll_to_selected recenter_pointer_on_display suppress_scroll_pointer_update' - + ' mark_current_list_as_read message_range message_in_table process_loaded_for_unread' - + ' mark_all_as_read message_unread process_read_messages unread_in_current_view' + + ' message_range message_in_table' + + ' message_unread unread_in_current_view' + ' fast_forward_pointer recent_subjects unread_subjects' + ' furthest_read server_furthest_read update_messages' + ' add_message_metadata' - + ' mark_message_as_read' + ' suppress_unread_counts' + ' msg_metadata_cache' + ' report_as_received'