mirror of
https://github.com/zulip/zulip.git
synced 2025-11-06 15:03:34 +00:00
We've been noticing a long delay between switching to a window with unread messages and the time that those messages actually appear. This got much worse around the time we added Notificon. Our hypothesis (supported by some testing) is that the work done by Notificon in creating a <canvas>, drawing into it, serializing it to PNG, etc. is using up some quota of background operations that would be better spent rendering messages. Switching to precomputed images should mitigate this problem. Resolves #896. May resolve #882 to our satisfaction. (imported from commit a2d98a163486bdd35fdfb5351f96c5529ba5c7e9)
223 lines
7.2 KiB
JavaScript
223 lines
7.2 KiB
JavaScript
var notifications = (function () {
|
|
|
|
var exports = {};
|
|
|
|
var notice_memory = {};
|
|
var window_has_focus = true;
|
|
var new_message_count = 0;
|
|
var asked_permission_already = false;
|
|
var names;
|
|
|
|
function browser_desktop_notifications_on () {
|
|
return (window.webkitNotifications &&
|
|
// Firefox on Ubuntu claims to do webkitNotifications but its notifications are terrible
|
|
$.browser.webkit &&
|
|
// 0 is PERMISSION_ALLOWED
|
|
window.webkitNotifications.checkPermission() === 0);
|
|
}
|
|
|
|
function update_title_count(new_count) {
|
|
// Update window title and favicon to reflect new_message_count.
|
|
//
|
|
// If new_count is given, set new_message_count to that first.
|
|
var n;
|
|
|
|
if (new_count !== undefined) {
|
|
if (new_message_count === new_count)
|
|
return;
|
|
new_message_count = new_count;
|
|
}
|
|
|
|
document.title = (new_message_count ? ("(" + new_message_count + ") ") : "")
|
|
+ domain + " - Humbug";
|
|
|
|
// IE doesn't support PNG favicons, *shrug*
|
|
if (! $.browser.msie) {
|
|
// Indicate the message count in the favicon
|
|
if (new_message_count) {
|
|
// Make sure we're working with a number, as a defensive programming
|
|
// measure. And we don't have images above 99, so display those as
|
|
// 'infinite'.
|
|
n = (+new_message_count);
|
|
if (n > 99)
|
|
n = 'infinite';
|
|
|
|
util.set_favicon('/static/images/favicon/favicon-'+n+'.png');
|
|
} else {
|
|
util.set_favicon('/static/favicon.ico?v=2');
|
|
}
|
|
}
|
|
}
|
|
|
|
exports.initialize = function () {
|
|
names = fullname.toLowerCase().split(" ");
|
|
names.push(email.split("@")[0].toLowerCase());
|
|
names.push("all");
|
|
names.push("everyone");
|
|
names.push("<strong>" + fullname.toLowerCase() + "</strong>");
|
|
|
|
$(window).focus(function () {
|
|
window_has_focus = true;
|
|
update_title_count(0);
|
|
|
|
$.each(notice_memory, function (index, notice_mem_entry) {
|
|
notice_mem_entry.obj.cancel();
|
|
});
|
|
}).blur(function () {
|
|
window_has_focus = false;
|
|
}).mouseover(function () {
|
|
update_title_count(0);
|
|
});
|
|
|
|
if (!window.webkitNotifications) {
|
|
return;
|
|
}
|
|
|
|
$(document).click(function () {
|
|
if (!desktop_notifications_enabled || asked_permission_already) {
|
|
return;
|
|
}
|
|
if (window.webkitNotifications.checkPermission() !== 0) { // 0 is PERMISSION_ALLOWED
|
|
window.webkitNotifications.requestPermission();
|
|
asked_permission_already = true;
|
|
}
|
|
});
|
|
};
|
|
|
|
function gravatar_url(message) {
|
|
return "https://secure.gravatar.com/avatar/" + message.gravatar_hash +
|
|
"?d=identicon&s=30?stamp=" + ui.get_gravatar_stamp();
|
|
}
|
|
|
|
function process_desktop_notification(message) {
|
|
var i, notification_object, key;
|
|
var title = message.sender_full_name;
|
|
var content = $('<div/>').html(message.content).text();
|
|
var other_recipients;
|
|
var msg_count = 1;
|
|
|
|
if (message.type === "private") {
|
|
key = message.display_reply_to;
|
|
other_recipients = message.display_reply_to;
|
|
// Remove the sender from the list of other recipients
|
|
other_recipients = other_recipients.replace(", " + message.sender_full_name, "");
|
|
other_recipients = other_recipients.replace(message.sender_full_name + ", ", "");
|
|
} else {
|
|
key = message.sender_full_name + " to " +
|
|
message.display_recipient + " > " + message.subject;
|
|
}
|
|
|
|
if (content.length > 150) {
|
|
// Truncate content at a word boundary
|
|
for (i = 150; i > 0; i--) {
|
|
if (content[i] === ' ') {
|
|
break;
|
|
}
|
|
}
|
|
content = content.substring(0, i);
|
|
content += " [...]";
|
|
}
|
|
|
|
if (notice_memory[key] !== undefined) {
|
|
msg_count = notice_memory[key].msg_count + 1;
|
|
title = msg_count + " messages from " + title;
|
|
notification_object = notice_memory[key].obj;
|
|
// We must remove the .onclose so that it does not trigger on .cancel
|
|
notification_object.onclose = function () {};
|
|
notification_object.onclick = function () {};
|
|
notification_object.cancel();
|
|
}
|
|
|
|
if (message.type === "private" && message.display_recipient.length > 2) {
|
|
// If the message has too many recipients to list them all...
|
|
if (content.length + title.length + other_recipients.length > 230) {
|
|
// Then count how many people are in the conversation and summarize
|
|
// by saying the conversation is with "you and [number] other people"
|
|
other_recipients = other_recipients.replace(/[^,]/g, "").length +
|
|
" other people";
|
|
}
|
|
title += " (to you and " + other_recipients + ")";
|
|
}
|
|
if (message.type === "stream") {
|
|
title += " (to " + message.display_recipient + " > " + message.subject + ")";
|
|
}
|
|
|
|
notice_memory[key] = {
|
|
obj: window.webkitNotifications.createNotification(
|
|
gravatar_url(message), title, content),
|
|
msg_count: msg_count
|
|
};
|
|
notification_object = notice_memory[key].obj;
|
|
notification_object.onclick = function () {
|
|
notification_object.cancel();
|
|
delete notice_memory[key];
|
|
};
|
|
notification_object.onclose = function () {
|
|
delete notice_memory[key];
|
|
};
|
|
notification_object.show();
|
|
}
|
|
|
|
function speaking_at_me(message) {
|
|
var content_lc = message.content.toLowerCase();
|
|
var found_match = false, indexof, after_name, after_atname;
|
|
var punctuation = /[\.,-\/#!$%\^&\*;:{}=\-_`~()\+\?\[\]\s<>]/;
|
|
|
|
if (domain === "mit.edu") {
|
|
return false;
|
|
}
|
|
|
|
$.each(names, function (index, name) {
|
|
indexof = content_lc.indexOf(name.toLowerCase());
|
|
if (indexof === -1) {
|
|
// If there is no match, we don't need after_name
|
|
after_name = undefined;
|
|
} else if (indexof + name.length >= content_lc.length) {
|
|
// If the @name is at the end of the string, that's OK,
|
|
// so we set after_name to " " so that the code below
|
|
// will identify a match
|
|
after_name = " ";
|
|
} else {
|
|
after_name = content_lc.charAt(indexof + name.length);
|
|
}
|
|
if ((indexof === 0 &&
|
|
after_name.match(punctuation) !== null) ||
|
|
(indexof > 0 && content_lc.charAt(indexof-1) === "@" &&
|
|
after_name.match(punctuation) !== null)) {
|
|
found_match = true;
|
|
return false;
|
|
}
|
|
});
|
|
|
|
return found_match;
|
|
}
|
|
|
|
exports.received_messages = function (messages) {
|
|
var i, title_needs_update = false;
|
|
if (window_has_focus) {
|
|
return;
|
|
}
|
|
|
|
$.each(messages, function (index, message) {
|
|
if (message.sender_email !== email) {
|
|
new_message_count++;
|
|
title_needs_update = true;
|
|
|
|
if (desktop_notifications_enabled &&
|
|
browser_desktop_notifications_on() &&
|
|
(message.type === "private" ||
|
|
speaking_at_me(message))) {
|
|
process_desktop_notification(message);
|
|
}
|
|
}
|
|
});
|
|
|
|
if (title_needs_update) {
|
|
update_title_count();
|
|
}
|
|
};
|
|
|
|
return exports;
|
|
|
|
}());
|