diff --git a/.eslintrc.json b/.eslintrc.json index bd6e2ac9e1..614aa2b12e 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -36,6 +36,7 @@ "resize": false, "loading": false, "typing": false, + "typing_events": false, "typing_data": false, "typing_status": false, "compose": false, diff --git a/static/js/server_events.js b/static/js/server_events.js index 47dfd0379f..c7461f89dd 100644 --- a/static/js/server_events.js +++ b/static/js/server_events.js @@ -252,9 +252,9 @@ function dispatch_normal_event(event) { } if (event.op === 'start') { - typing.display_notification(event); + typing_events.display_notification(event); } else if (event.op === 'stop') { - typing.hide_notification(event); + typing_events.hide_notification(event); } break; diff --git a/static/js/typing.js b/static/js/typing.js index c6a989029d..74823205b6 100644 --- a/static/js/typing.js +++ b/static/js/typing.js @@ -1,13 +1,9 @@ var typing = (function () { var exports = {}; -// How long before we assume a client has gone away -// and expire its typing status -var TYPING_STARTED_EXPIRY_PERIOD = 15000; // 15s -// Note!: There are also timing constants in typing_status.js -// that make typing indicators work. - -var stop_typing_timers = new Dict(); +// This module handles the outbound side of typing indicators. +// We detect changes in the compose box and notify the server +// when we are typing. For the inbound side see typing_events.js. function send_typing_notification_ajax(recipients, operation) { channel.post({ @@ -95,83 +91,6 @@ $(document).on('compose_canceled.zulip compose_finished.zulip', function () { typing_status.stop(worker); }); -function get_users_typing_for_narrow() { - if (!narrow.narrowed_to_pms()) { - // Narrow is neither pm-with nor is: private - return []; - } - if (narrow.operators()[0].operator === 'pm-with') { - // Get list of users typing in this conversation - var narrow_emails_string = narrow.operators()[0].operand; - // TODO: Create people.emails_strings_to_user_ids. - var narrow_user_ids_string = people.emails_strings_to_user_ids_string(narrow_emails_string); - var narrow_user_ids = narrow_user_ids_string.split(',').map(function (user_id_string) { - return parseInt(user_id_string, 10); - }); - var group = narrow_user_ids.concat([page_params.user_id]); - return typing_data.get_group_typists(group); - } - // Get all users typing (in all private conversations with current user) - return typing_data.get_all_typists(); -} - -function render_notifications_for_narrow() { - var user_ids = get_users_typing_for_narrow(); - var users_typing = user_ids.map(people.get_person_from_user_id); - if (users_typing.length === 0) { - $('#typing_notifications').hide(); - } else { - $('#typing_notifications').html(templates.render('typing_notifications', {users: users_typing})); - $('#typing_notifications').show(); - } -} - -$(document).on('narrow_activated.zulip', render_notifications_for_narrow); -$(document).on('narrow_deactivated.zulip', render_notifications_for_narrow); - -exports.hide_notification = function (event) { - var recipients = event.recipients.map(function (user) { - return user.user_id; - }); - recipients.sort(); - - // If there's an existing timer for this typing notifications - // thread, clear it. - if (stop_typing_timers[recipients] !== undefined) { - clearTimeout(stop_typing_timers[recipients]); - stop_typing_timers[recipients] = undefined; - } - - var removed = typing_data.remove_typist(recipients, event.sender.user_id); - - if (removed) { - render_notifications_for_narrow(); - } -}; - -exports.display_notification = function (event) { - var recipients = event.recipients.map(function (user) { - return user.user_id; - }); - recipients.sort(); - - var sender_id = event.sender.user_id; - event.sender.name = people.get_person_from_user_id(sender_id).full_name; - - typing_data.add_typist(recipients, sender_id); - - render_notifications_for_narrow(); - // If there's an existing timeout for this typing notifications - // thread, clear it. - if (stop_typing_timers[recipients] !== undefined) { - clearTimeout(stop_typing_timers[recipients]); - } - // Set a time to expire the data if the sender stops transmitting - stop_typing_timers[recipients] = setTimeout(function () { - exports.hide_notification(event); - }, TYPING_STARTED_EXPIRY_PERIOD); -}; - return exports; }()); diff --git a/static/js/typing_events.js b/static/js/typing_events.js new file mode 100644 index 0000000000..fdbca816b6 --- /dev/null +++ b/static/js/typing_events.js @@ -0,0 +1,102 @@ +var typing_events = (function () { +var exports = {}; + +// This code handles the inbound side of typing notifications. +// When another user is typing, we process the events here. +// +// We also handle the local event of re-narrowing. +// (For the outbound code, see typing.js.) + +// How long before we assume a client has gone away +// and expire its typing status +var TYPING_STARTED_EXPIRY_PERIOD = 15000; // 15s + +// Note!: There are also timing constants in typing_status.js +// that make typing indicators work. + +var stop_typing_timers = new Dict(); + +function get_users_typing_for_narrow() { + if (!narrow.narrowed_to_pms()) { + // Narrow is neither pm-with nor is: private + return []; + } + if (narrow.operators()[0].operator === 'pm-with') { + // Get list of users typing in this conversation + var narrow_emails_string = narrow.operators()[0].operand; + // TODO: Create people.emails_strings_to_user_ids. + var narrow_user_ids_string = people.emails_strings_to_user_ids_string(narrow_emails_string); + var narrow_user_ids = narrow_user_ids_string.split(',').map(function (user_id_string) { + return parseInt(user_id_string, 10); + }); + var group = narrow_user_ids.concat([page_params.user_id]); + return typing_data.get_group_typists(group); + } + // Get all users typing (in all private conversations with current user) + return typing_data.get_all_typists(); +} + +function render_notifications_for_narrow() { + var user_ids = get_users_typing_for_narrow(); + var users_typing = user_ids.map(people.get_person_from_user_id); + if (users_typing.length === 0) { + $('#typing_notifications').hide(); + } else { + $('#typing_notifications').html(templates.render('typing_notifications', {users: users_typing})); + $('#typing_notifications').show(); + } +} + +exports.hide_notification = function (event) { + var recipients = event.recipients.map(function (user) { + return user.user_id; + }); + recipients.sort(); + + // If there's an existing timer for this typing notifications + // thread, clear it. + if (stop_typing_timers[recipients] !== undefined) { + clearTimeout(stop_typing_timers[recipients]); + stop_typing_timers[recipients] = undefined; + } + + var removed = typing_data.remove_typist(recipients, event.sender.user_id); + + if (removed) { + render_notifications_for_narrow(); + } +}; + +exports.display_notification = function (event) { + var recipients = event.recipients.map(function (user) { + return user.user_id; + }); + recipients.sort(); + + var sender_id = event.sender.user_id; + event.sender.name = people.get_person_from_user_id(sender_id).full_name; + + typing_data.add_typist(recipients, sender_id); + + render_notifications_for_narrow(); + // If there's an existing timeout for this typing notifications + // thread, clear it. + if (stop_typing_timers[recipients] !== undefined) { + clearTimeout(stop_typing_timers[recipients]); + } + // Set a time to expire the data if the sender stops transmitting + stop_typing_timers[recipients] = setTimeout(function () { + exports.hide_notification(event); + }, TYPING_STARTED_EXPIRY_PERIOD); +}; + +$(document).on('narrow_activated.zulip', render_notifications_for_narrow); +$(document).on('narrow_deactivated.zulip', render_notifications_for_narrow); + + +return exports; +}()); + +if (typeof module !== 'undefined') { + module.exports = typing_events; +} diff --git a/static/js/typing_status.js b/static/js/typing_status.js index 188d5e19dc..9f44ff5b7e 100644 --- a/static/js/typing_status.js +++ b/static/js/typing_status.js @@ -5,7 +5,7 @@ var exports = {}; // The following constants are tuned to work with // TYPING_STARTED_EXPIRY_PERIOD, which is what the other // users will use to time out our messages. (Or us, -// depending on your perspective.) See typing.js. +// depending on your perspective.) See typing_events.js. // How frequently 'still typing' notifications are sent // to extend the expiry diff --git a/zproject/settings.py b/zproject/settings.py index 775743be7a..02405d57a0 100644 --- a/zproject/settings.py +++ b/zproject/settings.py @@ -904,6 +904,7 @@ JS_SPECS = { 'js/typing.js', 'js/typing_status.js', 'js/typing_data.js', + 'js/typing_events.js', 'js/ui_init.js', 'js/shim.js', # JS bundled by webpack is also included here if PIPELINE_ENABLED setting is true