reactions.js: Migrate webapp to use the new reactions API.

Fixes: #6909.
This commit is contained in:
Harshit Bansal
2017-11-01 03:03:28 +05:30
committed by Tim Abbott
parent 6981ac3d2f
commit 8a4fc9970f
5 changed files with 257 additions and 109 deletions

View File

@@ -25,12 +25,21 @@ set_global('emoji', {
emoji_url: 'TBD', emoji_url: 'TBD',
deactivated: true, deactivated: true,
}, },
zulip: {
emoji_name: 'zulip',
emoji_url: 'TBD',
deactivated: false,
},
}, },
active_realm_emojis: { active_realm_emojis: {
realm_emoji: { realm_emoji: {
emoji_name: 'realm_emoji', emoji_name: 'realm_emoji',
emoji_url: 'TBD', emoji_url: 'TBD',
}, },
zulip: {
emoji_name: 'zulip',
emoji_url: 'TBD',
},
}, },
deactivated_realm_emojis: { deactivated_realm_emojis: {
inactive_realm_emoji: { inactive_realm_emoji: {
@@ -52,6 +61,8 @@ set_global('emoji_codes', {
name_to_codepoint: { name_to_codepoint: {
alien: '1f47d', alien: '1f47d',
smile: '1f604', smile: '1f604',
frown: '1f626',
octopus: '1f419',
}, },
}); });
set_global('emoji_picker', { set_global('emoji_picker', {
@@ -80,15 +91,15 @@ people.add_in_realm(cali);
var message = { var message = {
id: 1001, id: 1001,
reactions: [ reactions: [
{emoji_name: 'smile', user: {id: 5}, reaction_type: 'unicode_emoji', emoji_code: '1'}, {emoji_name: 'smile', user: {id: 5}, reaction_type: 'unicode_emoji', emoji_code: '1f604'},
{emoji_name: 'smile', user: {id: 6}, reaction_type: 'unicode_emoji', emoji_code: '1'}, {emoji_name: 'smile', user: {id: 6}, reaction_type: 'unicode_emoji', emoji_code: '1f604'},
{emoji_name: 'frown', user: {id: 7}, reaction_type: 'unicode_emoji', emoji_code: '2'}, {emoji_name: 'frown', user: {id: 7}, reaction_type: 'unicode_emoji', emoji_code: '1f626'},
{emoji_name: 'inactive_realm_emoji', user: {id: 5}, reaction_type: 'realm_emoji', {emoji_name: 'inactive_realm_emoji', user: {id: 5}, reaction_type: 'realm_emoji',
emoji_code: '1'}, emoji_code: 'inactive_realm_emoji'},
// add some bogus user_ids // add some bogus user_ids
{emoji_name: 'octopus', user: {id: 8888}, reaction_type: 'unicode_emoji', emoji_code: '3'}, {emoji_name: 'octopus', user: {id: 8888}, reaction_type: 'unicode_emoji', emoji_code: '1f419'},
{emoji_name: 'frown', user: {id: 9999}, reaction_type: 'unicode_emoji', emoji_code: '2'}, {emoji_name: 'frown', user: {id: 9999}, reaction_type: 'unicode_emoji', emoji_code: '1f626'},
], ],
}; };
@@ -141,8 +152,8 @@ set_global('current_msg_list', {
(function test_basics() { (function test_basics() {
var result = reactions.get_message_reactions(message); var result = reactions.get_message_reactions(message);
assert(reactions.current_user_has_reacted_to_emoji(message, 'smile')); assert(reactions.current_user_has_reacted_to_emoji(message, '1f604', 'unicode_emoji'));
assert(!reactions.current_user_has_reacted_to_emoji(message, 'frown')); assert(!reactions.current_user_has_reacted_to_emoji(message, '1f626', 'unicode_emoji'));
result.sort(function (a, b) { return a.count - b.count; }); result.sort(function (a, b) { return a.count - b.count; });
@@ -150,8 +161,8 @@ set_global('current_msg_list', {
{ {
emoji_name: 'frown', emoji_name: 'frown',
reaction_type: 'unicode_emoji', reaction_type: 'unicode_emoji',
emoji_code: '2', emoji_code: '1f626',
emoji_name_css_class: '2', local_id: 'unicode_emoji,frown,1f626',
count: 1, count: 1,
user_ids: [7], user_ids: [7],
title: 'Cali reacted with :frown:', title: 'Cali reacted with :frown:',
@@ -161,8 +172,8 @@ set_global('current_msg_list', {
{ {
emoji_name: 'inactive_realm_emoji', emoji_name: 'inactive_realm_emoji',
reaction_type: 'realm_emoji', reaction_type: 'realm_emoji',
emoji_code: '1', emoji_code: 'inactive_realm_emoji',
emoji_name_css_class: '1', local_id: 'realm_emoji,inactive_realm_emoji,inactive_realm_emoji',
count: 1, count: 1,
user_ids: [5], user_ids: [5],
title: 'You (click to remove) reacted with :inactive_realm_emoji:', title: 'You (click to remove) reacted with :inactive_realm_emoji:',
@@ -174,8 +185,8 @@ set_global('current_msg_list', {
{ {
emoji_name: 'smile', emoji_name: 'smile',
reaction_type: 'unicode_emoji', reaction_type: 'unicode_emoji',
emoji_code: '1', emoji_code: '1f604',
emoji_name_css_class: '1', local_id: 'unicode_emoji,smile,1f604',
count: 2, count: 2,
user_ids: [5, 6], user_ids: [5, 6],
title: 'You (click to remove) and Bob van Roberts reacted with :smile:', title: 'You (click to remove) and Bob van Roberts reacted with :smile:',
@@ -194,8 +205,12 @@ set_global('current_msg_list', {
global.channel.del = stub.f; global.channel.del = stub.f;
reactions.toggle_emoji_reaction(message_id, emoji_name); reactions.toggle_emoji_reaction(message_id, emoji_name);
var args = stub.get_args('args').args; var args = stub.get_args('args').args;
assert.equal(args.url, '/json/messages/1001/emoji_reactions/smile'); assert.equal(args.url, '/json/messages/1001/reactions');
assert.deepEqual(args.data, {
reaction_type: 'unicode_emoji',
emoji_name: 'smile',
emoji_code: '1f604',
});
// args.success() does nothing; just make sure it doesn't crash // args.success() does nothing; just make sure it doesn't crash
args.success(); args.success();
@@ -206,10 +221,15 @@ set_global('current_msg_list', {
emoji_name = 'alien'; // not set yet emoji_name = 'alien'; // not set yet
global.with_stub(function (stub) { global.with_stub(function (stub) {
global.channel.put = stub.f; global.channel.post = stub.f;
reactions.toggle_emoji_reaction(message_id, emoji_name); reactions.toggle_emoji_reaction(message_id, emoji_name);
var args = stub.get_args('args').args; var args = stub.get_args('args').args;
assert.equal(args.url, '/json/messages/1001/emoji_reactions/alien'); assert.equal(args.url, '/json/messages/1001/reactions');
assert.deepEqual(args.data, {
reaction_type: 'unicode_emoji',
emoji_name: 'alien',
emoji_code: '1f47d',
});
}); });
emoji_name = 'inactive_realm_emoji'; // Test removing a deactivated realm emoji. emoji_name = 'inactive_realm_emoji'; // Test removing a deactivated realm emoji.
@@ -217,11 +237,36 @@ set_global('current_msg_list', {
global.channel.del = stub.f; global.channel.del = stub.f;
reactions.toggle_emoji_reaction(message_id, emoji_name); reactions.toggle_emoji_reaction(message_id, emoji_name);
var args = stub.get_args('args').args; var args = stub.get_args('args').args;
assert.equal(args.url, '/json/messages/1001/emoji_reactions/inactive_realm_emoji'); assert.equal(args.url, '/json/messages/1001/reactions');
assert.deepEqual(args.data, {
reaction_type: 'realm_emoji',
emoji_name: 'inactive_realm_emoji',
emoji_code: 'inactive_realm_emoji',
});
}); });
emoji_name = 'unknown-emoji'; emoji_name = 'zulip'; // Test adding zulip emoji.
global.with_stub(function (stub) {
global.channel.post = stub.f;
reactions.toggle_emoji_reaction(message_id, emoji_name); reactions.toggle_emoji_reaction(message_id, emoji_name);
var args = stub.get_args('args').args;
assert.equal(args.url, '/json/messages/1001/reactions');
assert.deepEqual(args.data, {
reaction_type: 'zulip_extra_emoji',
emoji_name: 'zulip',
emoji_code: 'zulip',
});
});
var orig_func = global.blueslip.warn;
var error_msg;
global.blueslip.warn = function (msg) {
error_msg = msg;
};
emoji_name = 'unknown-emoji'; // Test sending an emoji unknown to frontend.
reactions.toggle_emoji_reaction(message_id, emoji_name);
assert.equal(error_msg, 'Bad emoji name: ' + emoji_name);
global.blueslip.warn = orig_func;
}()); }());
(function test_set_reaction_count() { (function test_set_reaction_count() {
@@ -252,7 +297,9 @@ set_global('current_msg_list', {
// Insert 8ball for Alice. // Insert 8ball for Alice.
var alice_event = { var alice_event = {
message_id: 1001, message_id: 1001,
reaction_type: 'unicode_emoji',
emoji_name: '8ball', emoji_name: '8ball',
emoji_code: '1f3b1',
user: { user: {
user_id: alice.user_id, user_id: alice.user_id,
}, },
@@ -296,7 +343,9 @@ set_global('current_msg_list', {
var bob_event = { var bob_event = {
message_id: 1001, message_id: 1001,
reaction_type: 'unicode_emoji',
emoji_name: '8ball', emoji_name: '8ball',
emoji_code: '1f3b1',
user: { user: {
user_id: bob.user_id, user_id: bob.user_id,
}, },
@@ -316,7 +365,7 @@ set_global('current_msg_list', {
}; };
message_reactions.find = function (selector) { message_reactions.find = function (selector) {
assert.equal(selector, "[data-emoji-name='8ball']"); assert.equal(selector, "[data-reaction-id='unicode_emoji,8ball,1f3b1']");
return reaction_element; return reaction_element;
}; };
@@ -358,7 +407,9 @@ set_global('current_msg_list', {
// Now add Cali's realm_emoji reaction. // Now add Cali's realm_emoji reaction.
var cali_event = { var cali_event = {
message_id: 1001, message_id: 1001,
reaction_type: 'realm_emoji',
emoji_name: 'realm_emoji', emoji_name: 'realm_emoji',
emoji_code: 'realm_emoji',
user: { user: {
user_id: cali.user_id, user_id: cali.user_id,
}, },
@@ -384,14 +435,16 @@ set_global('current_msg_list', {
// And then have Alice update it. // And then have Alice update it.
alice_event = { alice_event = {
message_id: 1001, message_id: 1001,
reaction_type: 'realm_emoji',
emoji_name: 'realm_emoji', emoji_name: 'realm_emoji',
emoji_code: 'realm_emoji',
user: { user: {
user_id: alice.user_id, user_id: alice.user_id,
}, },
}; };
message_reactions.find = function (selector) { message_reactions.find = function (selector) {
assert.equal(selector, "[data-emoji-name='realm_emoji']"); assert.equal(selector, "[data-reaction-id='realm_emoji,realm_emoji,realm_emoji']");
return reaction_element; return reaction_element;
}; };
reaction_element.prop = function () {}; reaction_element.prop = function () {};
@@ -450,7 +503,9 @@ set_global('current_msg_list', {
var alice_8ball_event = { var alice_8ball_event = {
message_id: 2001, message_id: 2001,
reaction_type: 'unicode_emoji',
emoji_name: '8ball', emoji_name: '8ball',
emoji_code: '1f3b1',
user: { user: {
user_id: alice.user_id, user_id: alice.user_id,
}, },
@@ -458,7 +513,9 @@ set_global('current_msg_list', {
var bob_8ball_event = { var bob_8ball_event = {
message_id: 2001, message_id: 2001,
reaction_type: 'unicode_emoji',
emoji_name: '8ball', emoji_name: '8ball',
emoji_code: '1f3b1',
user: { user: {
user_id: bob.user_id, user_id: bob.user_id,
}, },
@@ -466,7 +523,9 @@ set_global('current_msg_list', {
var cali_airplane_event = { var cali_airplane_event = {
message_id: 2001, message_id: 2001,
reaction_type: 'unicode_emoji',
emoji_name: 'airplane', emoji_name: 'airplane',
emoji_code: '2708',
user: { user: {
user_id: cali.user_id, user_id: cali.user_id,
}, },
@@ -481,7 +540,9 @@ set_global('current_msg_list', {
name: 'insert_new_reaction', name: 'insert_new_reaction',
opts: { opts: {
message_id: 2001, message_id: 2001,
reaction_type: 'unicode_emoji',
emoji_name: '8ball', emoji_name: '8ball',
emoji_code: '1f3b1',
user_id: alice.user_id, user_id: alice.user_id,
}, },
}, },
@@ -497,7 +558,9 @@ set_global('current_msg_list', {
name: 'update_existing_reaction', name: 'update_existing_reaction',
opts: { opts: {
message_id: 2001, message_id: 2001,
reaction_type: 'unicode_emoji',
emoji_name: '8ball', emoji_name: '8ball',
emoji_code: '1f3b1',
user_id: bob.user_id, user_id: bob.user_id,
user_list: [alice.user_id, bob.user_id], user_list: [alice.user_id, bob.user_id],
}, },
@@ -514,7 +577,9 @@ set_global('current_msg_list', {
name: 'insert_new_reaction', name: 'insert_new_reaction',
opts: { opts: {
message_id: 2001, message_id: 2001,
reaction_type: 'unicode_emoji',
emoji_name: 'airplane', emoji_name: 'airplane',
emoji_code: '2708',
user_id: cali.user_id, user_id: cali.user_id,
}, },
}, },
@@ -530,7 +595,9 @@ set_global('current_msg_list', {
name: 'remove_reaction', name: 'remove_reaction',
opts: { opts: {
message_id: 2001, message_id: 2001,
reaction_type: 'unicode_emoji',
emoji_name: '8ball', emoji_name: '8ball',
emoji_code: '1f3b1',
user_id: bob.user_id, user_id: bob.user_id,
user_list: [alice.user_id], user_list: [alice.user_id],
}, },
@@ -547,7 +614,9 @@ set_global('current_msg_list', {
name: 'remove_reaction', name: 'remove_reaction',
opts: { opts: {
message_id: 2001, message_id: 2001,
reaction_type: 'unicode_emoji',
emoji_name: '8ball', emoji_name: '8ball',
emoji_code: '1f3b1',
user_id: alice.user_id, user_id: alice.user_id,
user_list: [], user_list: [],
}, },
@@ -575,8 +644,12 @@ set_global('current_msg_list', {
user_id: 99, user_id: 99,
}, },
}; };
reactions.toggle_emoji_reaction(55);
var original_func = reactions.current_user_has_reacted_to_emoji;
reactions.current_user_has_reacted_to_emoji = function () { return true; };
reactions.toggle_emoji_reaction(55, bogus_event.emoji_name);
assert.equal(error_msg, 'reactions: Bad message id: 55'); assert.equal(error_msg, 'reactions: Bad message id: 55');
reactions.current_user_has_reacted_to_emoji = original_func;
error_msg = undefined; error_msg = undefined;
reactions.add_reaction(bogus_event); reactions.add_reaction(bogus_event);
@@ -585,3 +658,50 @@ set_global('current_msg_list', {
reactions.remove_reaction(bogus_event); reactions.remove_reaction(bogus_event);
assert.equal(error_msg, undefined); assert.equal(error_msg, undefined);
}()); }());
(function test_local_reaction_id() {
var reaction_info = {
reaction_type: 'unicode_emoji',
emoji_name: 'thumbs_up',
emoji_code: '1f44d',
};
var local_id = reactions.get_local_reaction_id(reaction_info);
assert.equal(local_id, 'unicode_emoji,thumbs_up,1f44d');
var reverse_info = reactions.get_reaction_info(local_id);
assert.deepEqual(reverse_info, reaction_info);
}());
(function test_process_reaction_click() {
var message_id = 1001;
var expected_reaction_info = {
reaction_type: 'unicode_emoji',
emoji_name: '8ball',
emoji_code: '1f3b1',
};
global.message_store.get = function (message_id) {
assert.equal(message_id, 1001);
return message;
};
global.with_stub(function (stub) {
global.channel.post = stub.f;
reactions.process_reaction_click(message_id, 'unicode_emoji,8ball,1f3b1');
var args = stub.get_args('args').args;
assert.equal(args.url, '/json/messages/1001/reactions');
assert.deepEqual(args.data, expected_reaction_info);
});
expected_reaction_info = {
reaction_type: 'unicode_emoji',
emoji_name: 'smile',
emoji_code: '1f604',
};
global.with_stub(function (stub) {
global.channel.del = stub.f;
reactions.process_reaction_click(message_id, 'unicode_emoji,smile,1f604');
var args = stub.get_args('args').args;
assert.equal(args.url, '/json/messages/1001/reactions');
assert.deepEqual(args.data, expected_reaction_info);
});
}());

View File

@@ -852,7 +852,10 @@ function render(template_name, args) {
(function message_reaction() { (function message_reaction() {
var args = { var args = {
class: 'message_reaction',
emoji_name: 'smile', emoji_name: 'smile',
emoji_code: '1f604',
local_id: 'unicode_emoji,smile,1f604',
message_id: '1', message_id: '1',
}; };
@@ -861,8 +864,10 @@ function render(template_name, args) {
html += render('message_reaction', args); html += render('message_reaction', args);
html += '</div>'; html += '</div>';
var reaction = $(html).find(".message_reaction");
assert.equal(reaction.data("reaction-id"), "unicode_emoji,smile,1f604");
assert(reaction.find(".emoji").hasClass("emoji-1f604"));
global.write_handlebars_output("message_reaction", html); global.write_handlebars_output("message_reaction", html);
assert($(html).find(".message_reaction").has(".emoji .emoji-smile"));
}()); }());
(function more_topics() { (function more_topics() {

View File

@@ -178,9 +178,9 @@ $(function () {
$("#main_div").on("click", ".message_reaction", function (e) { $("#main_div").on("click", ".message_reaction", function (e) {
e.stopPropagation(); e.stopPropagation();
var emoji_name = $(this).attr('data-emoji-name'); var local_id = $(this).attr('data-reaction-id');
var message_id = rows.get_message_id(this); var message_id = rows.get_message_id(this);
reactions.toggle_emoji_reaction(message_id, emoji_name); reactions.process_reaction_click(message_id, local_id);
}); });
$("#main_div").on("click", "a.stream", function (e) { $("#main_div").on("click", "a.stream", function (e) {

View File

@@ -3,6 +3,21 @@ var exports = {};
exports.view = {}; // function namespace exports.view = {}; // function namespace
exports.get_local_reaction_id = function (reaction_info) {
return [reaction_info.reaction_type,
reaction_info.emoji_name,
reaction_info.emoji_code].join(',');
};
exports.get_reaction_info = function (reaction_id) {
var reaction_info = reaction_id.split(',');
return {
reaction_type: reaction_info[0],
emoji_name: reaction_info[1],
emoji_code: reaction_info[2],
};
};
exports.open_reactions_popover = function () { exports.open_reactions_popover = function () {
var message = current_msg_list.selected_message(); var message = current_msg_list.selected_message();
var target = $(current_msg_list.selected_row()).find(".actions_hover")[0]; var target = $(current_msg_list.selected_row()).find(".actions_hover")[0];
@@ -13,38 +28,37 @@ exports.open_reactions_popover = function () {
return true; return true;
}; };
function should_send_reaction(emoji_name, operation) { exports.current_user_has_reacted_to_emoji = function (message, emoji_code, type) {
// If a default emoji with this name exists then always send it irrespective var user_id = page_params.user_id;
// of whether a realm emoji with this name exists or not. return _.any(message.reactions, function (r) {
if (!emoji_codes.name_to_codepoint.hasOwnProperty(emoji_name)) { return (r.user.id === user_id) &&
// When the user attempts to add a reaction for a given emoji (r.reaction_type === type) &&
// name, and a built-in emoji with this name doesn't exist, (r.emoji_code === emoji_code);
// then send the request only if there is an active realm });
// emoji with this name. };
//
// This behavior isn't exactly correct: A user should be add
// their support to an emoji reaction for a deactivated (no
// longer available for new messages) realm emoji, but more
// backend work is required to support that anyway.
if (operation === "add") {
return emoji.active_realm_emojis.hasOwnProperty(emoji_name);
}
// While removing a reaction and a default emoji with this name doesn't
// exist then send the request if there is any realm emoji with this name
// whether active or inactive.
return emoji.all_realm_emojis.hasOwnProperty(emoji_name);
}
return true;
}
function send_reaction_ajax(message_id, emoji_name, operation) { function get_message(message_id) {
if (!should_send_reaction(emoji_name, operation)) { var message = message_store.get(message_id);
// Emoji doesn't exist if (!message) {
blueslip.error('reactions: Bad message id: ' + message_id);
return; return;
} }
return message;
}
function send_reaction_ajax(message_id, reaction_info) {
var message = get_message(message_id);
var has_reacted = exports.current_user_has_reacted_to_emoji(
message,
reaction_info.emoji_code,
reaction_info.reaction_type
);
var operation = has_reacted ? 'remove' : 'add';
var args = { var args = {
url: '/json/messages/' + message_id + '/emoji_reactions/' + encodeURIComponent(emoji_name), url: '/json/messages/' + message_id + '/reactions',
data: {}, data: reaction_info,
success: function () {}, success: function () {},
error: function (xhr) { error: function (xhr) {
var response = channel.xhr_error_message("Error sending reaction", xhr); var response = channel.xhr_error_message("Error sending reaction", xhr);
@@ -57,56 +71,55 @@ function send_reaction_ajax(message_id, emoji_name, operation) {
}, },
}; };
if (operation === 'add') { if (operation === 'add') {
channel.put(args); channel.post(args);
} else if (operation === 'remove') { } else if (operation === 'remove') {
channel.del(args); channel.del(args);
} }
} }
exports.current_user_has_reacted_to_emoji = function (message, emoji_name) { function get_user_list_for_message_reaction(message, local_id) {
var user_id = page_params.user_id;
return _.any(message.reactions, function (r) {
return (r.user.id === user_id) && (r.emoji_name === emoji_name);
});
};
function get_user_list_for_message_reaction(message, emoji_name) {
var matching_reactions = message.reactions.filter(function (reaction) { var matching_reactions = message.reactions.filter(function (reaction) {
return reaction.emoji_name === emoji_name; return reaction.local_id === local_id;
}); });
return matching_reactions.map(function (reaction) { return matching_reactions.map(function (reaction) {
return reaction.user.id; return reaction.user.id;
}); });
} }
function get_message(message_id) {
var message = message_store.get(message_id);
if (!message) {
blueslip.error('reactions: Bad message id: ' + message_id);
return;
}
return message;
}
exports.toggle_emoji_reaction = function (message_id, emoji_name) { exports.toggle_emoji_reaction = function (message_id, emoji_name) {
// This toggles the current user's reaction to the clicked emoji. // This toggles the current user's reaction to the clicked emoji.
var reaction_info = {
emoji_name: emoji_name,
};
var message = get_message(message_id); if (emoji.all_realm_emojis.hasOwnProperty(emoji_name)) {
if (!message) { if (emoji_name === 'zulip') {
reaction_info.reaction_type = 'zulip_extra_emoji';
} else {
reaction_info.reaction_type = 'realm_emoji';
}
reaction_info.emoji_code = emoji_name;
} else if (emoji_codes.name_to_codepoint.hasOwnProperty(emoji_name)) {
reaction_info.reaction_type = 'unicode_emoji';
reaction_info.emoji_code = emoji_codes.name_to_codepoint[emoji_name];
} else {
blueslip.warn('Bad emoji name: ' + emoji_name);
return; return;
} }
var has_reacted = exports.current_user_has_reacted_to_emoji(message, emoji_name); send_reaction_ajax(message_id, reaction_info);
var operation = has_reacted ? 'remove' : 'add';
send_reaction_ajax(message_id, emoji_name, operation);
// The next line isn't always necessary, but it is harmless/quick // The next line isn't always necessary, but it is harmless/quick
// when no popovers are there. // when no popovers are there.
emoji_picker.hide_emoji_popover(); emoji_picker.hide_emoji_popover();
}; };
exports.process_reaction_click = function (message_id, local_id) {
var reaction_info = exports.get_reaction_info(local_id);
send_reaction_ajax(message_id, reaction_info);
};
function full_name(user_id) { function full_name(user_id) {
if (user_id === page_params.user_id) { if (user_id === page_params.user_id) {
return 'You (click to remove)'; return 'You (click to remove)';
@@ -135,9 +148,9 @@ exports.get_reaction_section = function (message_id) {
return section; return section;
}; };
exports.find_reaction = function (message_id, emoji_name) { exports.find_reaction = function (message_id, local_id) {
var reaction_section = exports.get_reaction_section(message_id); var reaction_section = exports.get_reaction_section(message_id);
var reaction = reaction_section.find("[data-emoji-name='" + emoji_name + "']"); var reaction = reaction_section.find("[data-reaction-id='" + local_id + "']");
return reaction; return reaction;
}; };
@@ -154,9 +167,8 @@ exports.set_reaction_count = function (reaction, count) {
exports.add_reaction = function (event) { exports.add_reaction = function (event) {
var message_id = event.message_id; var message_id = event.message_id;
var emoji_name = event.emoji_name;
var message = message_store.get(message_id); var message = message_store.get(message_id);
if (message === undefined) { if (message === undefined) {
// If we don't have the message in cache, do nothing; if we // If we don't have the message in cache, do nothing; if we
// ever fetch it from the server, it'll come with the // ever fetch it from the server, it'll come with the
@@ -165,24 +177,24 @@ exports.add_reaction = function (event) {
} }
event.user.id = event.user.user_id; event.user.id = event.user.user_id;
event.local_id = exports.get_local_reaction_id(event);
message.reactions.push(event); message.reactions.push(event);
var user_list = get_user_list_for_message_reaction(message, emoji_name); var user_list = get_user_list_for_message_reaction(message, event.local_id);
var opts = {
message_id: event.message_id,
reaction_type: event.reaction_type,
emoji_name: event.emoji_name,
emoji_code: event.emoji_code,
user_id: event.user.id,
};
if (user_list.length > 1) { if (user_list.length > 1) {
exports.view.update_existing_reaction({ opts.user_list = user_list;
message_id: event.message_id, exports.view.update_existing_reaction(opts);
emoji_name: event.emoji_name,
user_list: user_list,
user_id: event.user.id,
});
} else { } else {
exports.view.insert_new_reaction({ exports.view.insert_new_reaction(opts);
message_id: event.message_id,
emoji_name: event.emoji_name,
user_id: event.user.id,
});
} }
}; };
@@ -195,8 +207,8 @@ exports.view.update_existing_reaction = function (opts) {
var emoji_name = opts.emoji_name; var emoji_name = opts.emoji_name;
var user_list = opts.user_list; var user_list = opts.user_list;
var user_id = opts.user_id; var user_id = opts.user_id;
var local_id = exports.get_local_reaction_id(opts);
var reaction = exports.find_reaction(message_id, emoji_name); var reaction = exports.find_reaction(message_id, local_id);
exports.set_reaction_count(reaction, user_list.length); exports.set_reaction_count(reaction, user_list.length);
@@ -216,25 +228,27 @@ exports.view.insert_new_reaction = function (opts) {
var message_id = opts.message_id; var message_id = opts.message_id;
var emoji_name = opts.emoji_name; var emoji_name = opts.emoji_name;
var emoji_code = opts.emoji_code;
var user_id = opts.user_id; var user_id = opts.user_id;
var user_list = [user_id]; var user_list = [user_id];
var context = { var context = {
message_id: message_id, message_id: message_id,
emoji_name: emoji_name, emoji_name: emoji_name,
emoji_code: emoji_code,
}; };
var new_title = generate_title(emoji_name, user_list); var new_title = generate_title(emoji_name, user_list);
if (emoji.active_realm_emojis[emoji_name]) { if (opts.reaction_type !== 'unicode_emoji') {
context.is_realm_emoji = true; context.is_realm_emoji = true;
context.url = emoji.active_realm_emojis[emoji_name].emoji_url; context.url = emoji.all_realm_emojis[emoji_code].emoji_url;
} }
context.count = 1; context.count = 1;
context.title = new_title; context.title = new_title;
context.emoji_alt_code = page_params.emoji_alt_code; context.emoji_alt_code = page_params.emoji_alt_code;
context.emoji_name_css_class = emoji.emojis_name_to_css_class[emoji_name]; context.local_id = exports.get_local_reaction_id(opts);
if (opts.user_id === page_params.user_id) { if (opts.user_id === page_params.user_id) {
context.class = "message_reaction reacted"; context.class = "message_reaction reacted";
@@ -250,11 +264,14 @@ exports.view.insert_new_reaction = function (opts) {
}; };
exports.remove_reaction = function (event) { exports.remove_reaction = function (event) {
var reaction_type = event.reaction_type;
var emoji_name = event.emoji_name; var emoji_name = event.emoji_name;
var emoji_code = event.emoji_code;
var message_id = event.message_id; var message_id = event.message_id;
var user_id = event.user.user_id; var user_id = event.user.user_id;
var i = -1; var i = -1;
var message = message_store.get(message_id); var message = message_store.get(message_id);
var local_id = exports.get_local_reaction_id(event);
if (message === undefined) { if (message === undefined) {
// If we don't have the message in cache, do nothing; if we // If we don't have the message in cache, do nothing; if we
@@ -266,7 +283,7 @@ exports.remove_reaction = function (event) {
// Do the data part first: // Do the data part first:
// Remove reactions from our message object. // Remove reactions from our message object.
_.each(message.reactions, function (reaction, index) { _.each(message.reactions, function (reaction, index) {
if (reaction.emoji_name === emoji_name && reaction.user.id === user_id) { if (reaction.local_id === local_id && reaction.user.id === user_id) {
i = index; i = index;
} }
}); });
@@ -276,11 +293,13 @@ exports.remove_reaction = function (event) {
} }
// Compute the new user list for this reaction. // Compute the new user list for this reaction.
var user_list = get_user_list_for_message_reaction(message, emoji_name); var user_list = get_user_list_for_message_reaction(message, local_id);
exports.view.remove_reaction({ exports.view.remove_reaction({
message_id: message_id, message_id: message_id,
reaction_type: reaction_type,
emoji_name: emoji_name, emoji_name: emoji_name,
emoji_code: emoji_code,
user_list: user_list, user_list: user_list,
user_id: user_id, user_id: user_id,
}); });
@@ -292,8 +311,8 @@ exports.view.remove_reaction = function (opts) {
var emoji_name = opts.emoji_name; var emoji_name = opts.emoji_name;
var user_list = opts.user_list; var user_list = opts.user_list;
var user_id = opts.user_id; var user_id = opts.user_id;
var local_id = exports.get_local_reaction_id(opts);
var reaction = exports.find_reaction(message_id, emoji_name); var reaction = exports.find_reaction(message_id, local_id);
if (user_list.length === 0) { if (user_list.length === 0) {
// If this user was the only one reacting for this emoji, we simply // If this user was the only one reacting for this emoji, we simply
@@ -331,6 +350,7 @@ exports.get_message_reactions = function (message) {
var message_reactions = new Dict(); var message_reactions = new Dict();
_.each(message.reactions, function (reaction) { _.each(message.reactions, function (reaction) {
var user_id = reaction.user.id; var user_id = reaction.user.id;
reaction.local_id = exports.get_local_reaction_id(reaction);
if (!people.is_known_user_id(user_id)) { if (!people.is_known_user_id(user_id)) {
blueslip.warn('Unknown user_id ' + user_id + blueslip.warn('Unknown user_id ' + user_id +
'in reaction for message ' + message.id); 'in reaction for message ' + message.id);
@@ -338,14 +358,17 @@ exports.get_message_reactions = function (message) {
} }
reaction.user_ids = []; reaction.user_ids = [];
var collapsed_reaction = message_reactions.setdefault( var collapsed_reaction = message_reactions.setdefault(
reaction.emoji_name, reaction.local_id,
_.omit(reaction, 'user') _.omit(reaction, 'user')
); );
collapsed_reaction.user_ids.push(user_id); collapsed_reaction.user_ids.push(user_id);
}); });
var reactions = message_reactions.items().map(function (item) { var reactions = message_reactions.items().map(function (item) {
var reaction = item[1]; var reaction = item[1];
reaction.emoji_name_css_class = reaction.emoji_code; reaction.local_id = reaction.local_id;
reaction.reaction_type = reaction.reaction_type;
reaction.emoji_name = reaction.emoji_name;
reaction.emoji_code = reaction.emoji_code;
reaction.count = reaction.user_ids.length; reaction.count = reaction.user_ids.length;
reaction.title = generate_title(reaction.emoji_name, reaction.user_ids); reaction.title = generate_title(reaction.emoji_name, reaction.user_ids);
reaction.emoji_alt_code = page_params.emoji_alt_code; reaction.emoji_alt_code = page_params.emoji_alt_code;

View File

@@ -1,11 +1,11 @@
<div class="{{this.class}}" title="{{this.title}}" data-emoji-name="{{this.emoji_name}}"> <div class="{{this.class}}" title="{{this.title}}" data-reaction-id={{this.local_id}}>
{{#if this.emoji_alt_code}} {{#if this.emoji_alt_code}}
<div class="emoji_alt_code">&nbsp:{{this.emoji_name}}:</div> <div class="emoji_alt_code">&nbsp:{{this.emoji_name}}:</div>
{{else}} {{else}}
{{#if this.is_realm_emoji}} {{#if this.is_realm_emoji}}
<img src="{{this.url}}" class="emoji" /> <img src="{{this.url}}" class="emoji" />
{{else}} {{else}}
<div class="emoji emoji-{{this.emoji_name_css_class}}" /> <div class="emoji emoji-{{this.emoji_code}}" />
{{/if}} {{/if}}
{{/if}} {{/if}}
<div class="message_reaction_count">{{this.count}}</div> <div class="message_reaction_count">{{this.count}}</div>