diff --git a/.eslintrc.json b/.eslintrc.json index 0a80b5785c..8735899960 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -97,6 +97,7 @@ "home_msg_list": false, "pm_list": false, "unread_ui": false, + "unread_ops": false, "user_events": false, "Plotly": false, "emoji_codes": false, diff --git a/frontend_tests/node_tests/dispatch.js b/frontend_tests/node_tests/dispatch.js index f8ea4f5a5f..9218c694f1 100644 --- a/frontend_tests/node_tests/dispatch.js +++ b/frontend_tests/node_tests/dispatch.js @@ -749,7 +749,7 @@ with_overrides(function (override) { with_overrides(function (override) { // update_message_flags__read var event = event_fixtures.update_message_flags__read; - override('unread_ui.mark_messages_as_read', noop); + override('unread_ops.mark_messages_as_read', noop); global.with_stub(function (stub) { override('message_store.get', stub.f); diff --git a/static/js/click_handlers.js b/static/js/click_handlers.js index d26f7ceb6e..d10a8af7ba 100644 --- a/static/js/click_handlers.js +++ b/static/js/click_handlers.js @@ -70,7 +70,7 @@ $(function () { // lists. var message = ui.find_message(message_id); - unread_ui.mark_message_as_read(message); + unread_ops.mark_message_as_read(message); ui.update_starred(message.id, message.starred !== true); message_flags.send_starred([message], message.starred); } diff --git a/static/js/compose.js b/static/js/compose.js index ebda185030..28431e7914 100644 --- a/static/js/compose.js +++ b/static/js/compose.js @@ -608,7 +608,7 @@ exports.respond_to_message = function (opts) { return; } - unread_ui.mark_message_as_read(message); + unread_ops.mark_message_as_read(message); var stream = ''; var subject = ''; diff --git a/static/js/message_store.js b/static/js/message_store.js index 2a2748de68..35d736255a 100644 --- a/static/js/message_store.js +++ b/static/js/message_store.js @@ -226,7 +226,7 @@ function maybe_add_narrowed_messages(messages, msg_list, messages_are_new, local new_messages = _.map(new_messages, add_message_metadata); exports.add_messages(new_messages, msg_list, {messages_are_new: messages_are_new}); - unread_ui.process_visible(); + unread_ops.process_visible(); notifications.possibly_notify_new_messages_outside_viewport(new_messages, local_id); notifications.notify_messages_outside_current_search(elsewhere_messages); }, @@ -432,7 +432,7 @@ exports.insert_new_messages = function insert_new_messages(messages, local_id) { } } - unread_ui.process_visible(); + unread_ops.process_visible(); notifications.received_messages(messages); stream_list.update_streams_sidebar(); pm_list.update_private_messages(); diff --git a/static/js/narrow.js b/static/js/narrow.js index 2960eb7164..41815068b1 100644 --- a/static/js/narrow.js +++ b/static/js/narrow.js @@ -388,7 +388,7 @@ exports.by_subject = function (target_id, opts) { exports.by_recipient(target_id, opts); return; } - unread_ui.mark_message_as_read(original); + unread_ops.mark_message_as_read(original); var search_terms = [ {operator: 'stream', operand: original.stream}, {operator: 'topic', operand: original.subject}, @@ -402,7 +402,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 = message_store.get(target_id); - unread_ui.mark_message_as_read(message); + unread_ops.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 2ea12e365f..e4018c5319 100644 --- a/static/js/navigate.js +++ b/static/js/navigate.js @@ -32,7 +32,7 @@ exports.down = function (with_centering) { var current_msg_table = rows.get_table(current_msg_list.table_name); message_viewport.scrollTop(current_msg_table.outerHeight(true) - message_viewport.height() * 0.1); - unread_ui.mark_current_list_as_read(); + unread_ops.mark_current_list_as_read(); } }; @@ -49,7 +49,7 @@ exports.to_end = function () { message_viewport.last_movement_direction = 1; current_msg_list.select_id(next_id, {then_scroll: true, from_scroll: true}); - unread_ui.mark_current_list_as_read(); + unread_ops.mark_current_list_as_read(); }; exports.page_up = function () { @@ -63,7 +63,7 @@ exports.page_up = function () { exports.page_down = function () { if (message_viewport.at_bottom() && !current_msg_list.empty()) { current_msg_list.select_id(current_msg_list.last().id, {then_scroll: false}); - unread_ui.mark_current_list_as_read(); + unread_ops.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 abd0c0fece..22d4c9b12f 100644 --- a/static/js/notifications.js +++ b/static/js/notifications.js @@ -69,7 +69,7 @@ exports.initialize = function () { // Update many places on the DOM to reflect unread // counts. - unread_ui.process_visible(); + unread_ops.process_visible(); }).blur(function () { window_has_focus = false; diff --git a/static/js/pointer.js b/static/js/pointer.js index 1dccaafe33..639a57626a 100644 --- a/static/js/pointer.js +++ b/static/js/pointer.js @@ -61,7 +61,7 @@ exports.fast_forward_pointer = function () { url: '/json/users/me', idempotent: true, success: function (data) { - unread_ui.mark_all_as_read(function () { + unread_ops.mark_all_as_read(function () { pointer.furthest_read = data.max_message_id; unconditionally_send_pointer_update().then(function () { ui.change_tab_to('#home'); @@ -183,7 +183,7 @@ exports.initialize = function initialize() { } else { messages = event.msg_list.message_range(event.previously_selected, event.id); } - unread_ui.mark_messages_as_read(messages, {from: 'pointer'}); + unread_ops.mark_messages_as_read(messages, {from: 'pointer'}); } }); }; diff --git a/static/js/server_events.js b/static/js/server_events.js index a77a52c687..ecd4a9d3f5 100644 --- a/static/js/server_events.js +++ b/static/js/server_events.js @@ -303,7 +303,7 @@ function dispatch_normal_event(event) { var msgs_to_update = _.map(event.messages, function (message_id) { return message_store.get(message_id); }); - unread_ui.mark_messages_as_read(msgs_to_update, {from: "server"}); + unread_ops.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 ad71859168..45452cf127 100644 --- a/static/js/stream_list.js +++ b/static/js/stream_list.js @@ -448,7 +448,7 @@ $(function () { stream_li.addClass('active-filter'); } rebuild_recent_topics(op_stream[0]); - unread_ui.process_visible(); + unread_ops.process_visible(); } }); diff --git a/static/js/stream_popover.js b/static/js/stream_popover.js index 6962ef018b..edb0fe3b6d 100644 --- a/static/js/stream_popover.js +++ b/static/js/stream_popover.js @@ -211,7 +211,7 @@ exports.register_stream_handlers = function () { $('body').on('click', '.mark_stream_as_read', function (e) { var sub = stream_popover_sub(e); exports.hide_stream_popover(); - unread_ui.mark_stream_as_read(sub.name); + unread_ops.mark_stream_as_read(sub.name); e.stopPropagation(); }); @@ -347,7 +347,7 @@ exports.register_topic_handlers = function () { var topic = $(e.currentTarget).attr('data-topic-name'); exports.hide_topic_popover(); - unread_ui.mark_topic_as_read(sub.name, topic); + unread_ops.mark_topic_as_read(sub.name, topic); e.stopPropagation(); }); }; diff --git a/static/js/ui.js b/static/js/ui.js index 6ecc1cdf52..4ec811ccdb 100644 --- a/static/js/ui.js +++ b/static/js/ui.js @@ -213,7 +213,7 @@ exports.update_starred = function (message_id, starred) { return; } - unread_ui.mark_message_as_read(message); + unread_ops.mark_message_as_read(message); message.starred = starred; @@ -588,9 +588,9 @@ function scroll_finished() { } // When the window scrolls, it may cause some messages to // enter the screen and become read. Calling - // unread_ui.process_visible will update necessary + // unread_ops.process_visible will update necessary // data structures and DOM elements. - setTimeout(unread_ui.process_visible, 0); + setTimeout(unread_ops.process_visible, 0); } } @@ -607,7 +607,7 @@ var saved_compose_cursor = 0; $(function () { message_viewport.message_pane.scroll($.throttle(50, function () { - unread_ui.process_visible(); + unread_ops.process_visible(); scroll_finish(); })); diff --git a/static/js/unread_ops.js b/static/js/unread_ops.js new file mode 100644 index 0000000000..156ac4537f --- /dev/null +++ b/static/js/unread_ops.js @@ -0,0 +1,115 @@ +var unread_ops = (function () { + +var exports = {}; + +exports.mark_all_as_read = function mark_all_as_read(cont) { + _.each(message_list.all.all_messages(), function (msg) { + msg.flags = msg.flags || []; + msg.flags.push('read'); + }); + unread.declare_bankruptcy(); + unread_ui.update_unread_counts(); + + channel.post({ + url: '/json/messages/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 === message_list.narrowed) { + unread.messages_read_in_narrow = true; + } + + if (options.from !== "server") { + message_flags.send_read(message); + } + + message.flags = message.flags || []; + message.flags.push('read'); + message.unread = false; + unread.process_read_message(message, options); + home_msg_list.show_message_as_read(message, options); + message_list.all.show_message_as_read(message, options); + if (message_list.narrowed) { + message_list.narrowed.show_message_as_read(message, options); + } + notifications.close_notification(message); + processed = true; + }); + + if (processed) { + unread_ui.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() { + if (! notifications.window_has_focus()) { + return; + } + + if (feature_flags.mark_read_at_bottom) { + if (message_viewport.bottom_message_visible()) { + exports.mark_current_list_as_read(); + } + } else { + exports.mark_messages_as_read(message_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_messages(), options); +}; + +exports.mark_stream_as_read = function mark_stream_as_read(stream, cont) { + channel.post({ + url: '/json/messages/flags', + idempotent: true, + data: {messages: JSON.stringify([]), + all: false, + op: 'add', + flag: 'read', + stream_name: stream, + }, + success: cont}); +}; + +exports.mark_topic_as_read = function mark_topic_as_read(stream, topic, cont) { + channel.post({ + url: '/json/messages/flags', + idempotent: true, + data: {messages: JSON.stringify([]), + all: false, + op: 'add', + flag: 'read', + topic_name: topic, + stream_name: stream, + }, + success: cont}); +}; + + +return exports; +}()); +if (typeof module !== 'undefined') { + module.exports = unread_ops; +} diff --git a/static/js/unread_ui.js b/static/js/unread_ui.js index a20e5ce83d..01d3e4ad8c 100644 --- a/static/js/unread_ui.js +++ b/static/js/unread_ui.js @@ -69,111 +69,6 @@ exports.enable = function enable() { exports.update_unread_counts(); }; -exports.mark_all_as_read = function mark_all_as_read(cont) { - _.each(message_list.all.all_messages(), function (msg) { - msg.flags = msg.flags || []; - msg.flags.push('read'); - }); - unread.declare_bankruptcy(); - exports.update_unread_counts(); - - channel.post({ - url: '/json/messages/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 === message_list.narrowed) { - unread.messages_read_in_narrow = true; - } - - if (options.from !== "server") { - message_flags.send_read(message); - } - - message.flags = message.flags || []; - message.flags.push('read'); - message.unread = false; - unread.process_read_message(message, options); - home_msg_list.show_message_as_read(message, options); - message_list.all.show_message_as_read(message, options); - if (message_list.narrowed) { - message_list.narrowed.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() { - if (! notifications.window_has_focus()) { - return; - } - - if (feature_flags.mark_read_at_bottom) { - if (message_viewport.bottom_message_visible()) { - exports.mark_current_list_as_read(); - } - } else { - exports.mark_messages_as_read(message_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_messages(), options); -}; - -exports.mark_stream_as_read = function mark_stream_as_read(stream, cont) { - channel.post({ - url: '/json/messages/flags', - idempotent: true, - data: {messages: JSON.stringify([]), - all: false, - op: 'add', - flag: 'read', - stream_name: stream, - }, - success: cont}); -}; - -exports.mark_topic_as_read = function mark_topic_as_read(stream, topic, cont) { - channel.post({ - url: '/json/messages/flags', - idempotent: true, - data: {messages: JSON.stringify([]), - all: false, - op: 'add', - flag: 'read', - topic_name: topic, - stream_name: stream, - }, - success: cont}); -}; - function consider_bankruptcy() { // Until we've handled possibly declaring bankruptcy, don't show // unread counts since they only consider messages that are loaded diff --git a/zproject/settings.py b/zproject/settings.py index c74d6988e7..3e021ef71c 100644 --- a/zproject/settings.py +++ b/zproject/settings.py @@ -820,6 +820,7 @@ JS_SPECS = { 'js/channel.js', 'js/setup.js', 'js/unread_ui.js', + 'js/unread_ops.js', 'js/muting.js', 'js/muting_ui.js', 'js/message_viewport.js',