Commit 4cb9fd88 authored by JC Brand's avatar JC Brand

Refactor emojis so that JSON is fetch asynchronously

parent 4e440b03
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -647,6 +647,12 @@ domain_placeholder ...@@ -647,6 +647,12 @@ domain_placeholder
The placeholder text shown in the domain input on the registration form. The placeholder text shown in the domain input on the registration form.
emoji_json_path
---------------
* Default: ``emojis/``
emoji_image_path emoji_image_path
---------------- ----------------
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
describe("A chat room", function () { describe("A chat room", function () {
it("can be bookmarked", mock.initConverse( it("can be bookmarked", mock.initConverse(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'emojisInitialized'], {},
async function (done, _converse) { async function (done, _converse) {
await test_utils.waitUntilDiscoConfirmed( await test_utils.waitUntilDiscoConfirmed(
......
...@@ -117,11 +117,8 @@ ...@@ -117,11 +117,8 @@
let el = online_contacts[0]; let el = online_contacts[0];
const jid = el.textContent.trim().replace(/ /g,'.').toLowerCase() + '@montague.lit'; const jid = el.textContent.trim().replace(/ /g,'.').toLowerCase() + '@montague.lit';
el.click(); el.click();
await u.waitUntil(() => _converse.chatboxes.length == 2); await u.waitUntil(() => document.querySelectorAll("#conversejs .chatbox").length == 2);
expect(_converse.chatboxviews.trimChats).toHaveBeenCalled(); expect(_converse.chatboxviews.trimChats).toHaveBeenCalled();
// Check that new chat boxes are created to the left of the
// controlbox (but to the right of all existing chat boxes)
expect(document.querySelectorAll("#conversejs .chatbox").length).toBe(2);
online_contacts[1].click(); online_contacts[1].click();
await u.waitUntil(() => _converse.chatboxes.length == 3); await u.waitUntil(() => _converse.chatboxes.length == 3);
el = online_contacts[1]; el = online_contacts[1];
...@@ -174,7 +171,7 @@ ...@@ -174,7 +171,7 @@
})); }));
it("can be trimmed to conserve space", it("can be trimmed to conserve space",
mock.initConverse(null, ['rosterGroupsFetched'], {}, mock.initConverse(null, ['rosterGroupsFetched', 'emojisInitialized'], {},
async function (done, _converse) { async function (done, _converse) {
spyOn(_converse.chatboxviews, 'trimChats'); spyOn(_converse.chatboxviews, 'trimChats');
...@@ -462,8 +459,8 @@ ...@@ -462,8 +459,8 @@
toolbar.querySelector('li.toggle-smiley').click(); toolbar.querySelector('li.toggle-smiley').click();
await u.waitUntil(() => u.isVisible(view.el.querySelector('.toggle-smiley .emoji-picker-container'))); await u.waitUntil(() => u.isVisible(view.el.querySelector('.toggle-smiley .emoji-picker-container')));
var picker = view.el.querySelector('.toggle-smiley .emoji-picker-container'); const picker = view.el.querySelector('.toggle-smiley .emoji-picker-container');
var items = picker.querySelectorAll('.emoji-picker li'); const items = picker.querySelectorAll('.emoji-picker li');
items[0].click() items[0].click()
expect(view.insertEmoji).toHaveBeenCalled(); expect(view.insertEmoji).toHaveBeenCalled();
expect(view.el.querySelector('textarea.chat-textarea').value).toBe(':grinning: '); expect(view.el.querySelector('textarea.chat-textarea').value).toBe(':grinning: ');
...@@ -960,7 +957,7 @@ ...@@ -960,7 +957,7 @@
it("is sent if the user has stopped typing since 2 minutes", it("is sent if the user has stopped typing since 2 minutes",
mock.initConverse( mock.initConverse(
null, ['rosterGroupsFetched', 'chatBoxesFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched', 'emojisInitialized'], {},
async function (done, _converse) { async function (done, _converse) {
const sent_stanzas = _converse.connection.sent_stanzas; const sent_stanzas = _converse.connection.sent_stanzas;
...@@ -1264,7 +1261,7 @@ ...@@ -1264,7 +1261,7 @@
it("is incremented from zero when chatbox was closed after viewing previously received messages and the window is not focused now", it("is incremented from zero when chatbox was closed after viewing previously received messages and the window is not focused now",
mock.initConverse( mock.initConverse(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'emojisInitialized'], {},
async function (done, _converse) { async function (done, _converse) {
await test_utils.waitForRoster(_converse, 'current'); await test_utils.waitForRoster(_converse, 'current');
...@@ -1347,7 +1344,7 @@ ...@@ -1347,7 +1344,7 @@
})); }));
it("is incremeted when message is received, chatbox is scrolled down and the window is not focused", it("is incremeted when message is received, chatbox is scrolled down and the window is not focused",
mock.initConverse(null, ['rosterGroupsFetched', 'chatBoxesFetched'], {}, mock.initConverse(null, ['rosterGroupsFetched', 'chatBoxesFetched', 'emojisInitialized'], {},
async function (done, _converse) { async function (done, _converse) {
await test_utils.waitForRoster(_converse, 'current'); await test_utils.waitForRoster(_converse, 'current');
...@@ -1367,7 +1364,7 @@ ...@@ -1367,7 +1364,7 @@
it("is incremeted when message is received, chatbox is scrolled up and the window is not focused", it("is incremeted when message is received, chatbox is scrolled up and the window is not focused",
mock.initConverse( mock.initConverse(
null, ['rosterGroupsFetched', 'chatBoxesFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched', 'emojisInitialized'], {},
async function (done, _converse) { async function (done, _converse) {
await test_utils.waitForRoster(_converse, 'current', 1); await test_utils.waitForRoster(_converse, 'current', 1);
...@@ -1385,7 +1382,7 @@ ...@@ -1385,7 +1382,7 @@
it("is cleared when ChatBoxView was scrolled down and the window become focused", it("is cleared when ChatBoxView was scrolled down and the window become focused",
mock.initConverse( mock.initConverse(
null, ['rosterGroupsFetched', 'chatBoxesFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched', 'emojisInitialized'], {},
async function (done, _converse) { async function (done, _converse) {
await test_utils.waitForRoster(_converse, 'current', 1); await test_utils.waitForRoster(_converse, 'current', 1);
...@@ -1404,7 +1401,7 @@ ...@@ -1404,7 +1401,7 @@
it("is not cleared when ChatBoxView was scrolled up and the windows become focused", it("is not cleared when ChatBoxView was scrolled up and the windows become focused",
mock.initConverse( mock.initConverse(
null, ['rosterGroupsFetched', 'chatBoxesFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched', 'emojisInitialized'], {},
async function (done, _converse) { async function (done, _converse) {
await test_utils.waitForRoster(_converse, 'current', 1); await test_utils.waitForRoster(_converse, 'current', 1);
...@@ -1509,20 +1506,21 @@ ...@@ -1509,20 +1506,21 @@
it("is cleared when unread messages are viewed which were received in scrolled-up chatbox", it("is cleared when unread messages are viewed which were received in scrolled-up chatbox",
mock.initConverse( mock.initConverse(
null, ['rosterGroupsFetched', 'chatBoxesFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched', 'emojisInitialized'], {},
async function (done, _converse) { async function (done, _converse) {
test_utils.openControlBox();
await test_utils.waitForRoster(_converse, 'current', 1); await test_utils.waitForRoster(_converse, 'current', 1);
const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit'; const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
await u.waitUntil(() => _converse.rosterview.el.querySelectorAll('.roster-group').length, 500); await u.waitUntil(() => _converse.rosterview.el.querySelectorAll('.roster-group').length, 500);
await test_utils.openChatBoxFor(_converse, sender_jid); await test_utils.openChatBoxFor(_converse, sender_jid);
const chatbox = _converse.chatboxes.get(sender_jid); const chatbox = _converse.chatboxes.get(sender_jid);
const view = _converse.chatboxviews.get(sender_jid);
const msgFactory = () => test_utils.createChatMessage(_converse, sender_jid, 'This message will be received as unread, but eventually will be read'); const msgFactory = () => test_utils.createChatMessage(_converse, sender_jid, 'This message will be received as unread, but eventually will be read');
const selector = 'a.open-chat:contains("' + chatbox.get('nickname') + '") .msgs-indicator'; const selector = `a.open-chat:contains("${chatbox.get('nickname')}") .msgs-indicator`;
const select_msgs_indicator = () => sizzle(selector, _converse.rosterview.el).pop(); const select_msgs_indicator = () => sizzle(selector, _converse.rosterview.el).pop();
chatbox.save('scrolled', true); chatbox.save('scrolled', true);
_converse.chatboxes.onMessage(msgFactory()); _converse.chatboxes.onMessage(msgFactory());
const view = _converse.chatboxviews.get(sender_jid);
await u.waitUntil(() => view.model.messages.length); await u.waitUntil(() => view.model.messages.length);
expect(select_msgs_indicator().textContent).toBe('1'); expect(select_msgs_indicator().textContent).toBe('1');
view.viewUnreadMessages(); view.viewUnreadMessages();
...@@ -1533,7 +1531,7 @@ ...@@ -1533,7 +1531,7 @@
it("is not cleared after user clicks on roster view when chatbox is already opened and scrolled up", it("is not cleared after user clicks on roster view when chatbox is already opened and scrolled up",
mock.initConverse( mock.initConverse(
null, ['rosterGroupsFetched', 'chatBoxesFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched', 'emojisInitialized'], {},
async function (done, _converse) { async function (done, _converse) {
await test_utils.waitForRoster(_converse, 'current', 1); await test_utils.waitForRoster(_converse, 'current', 1);
...@@ -1560,7 +1558,7 @@ ...@@ -1560,7 +1558,7 @@
it("is displayed when scrolled up chatbox is minimized after receiving unread messages", it("is displayed when scrolled up chatbox is minimized after receiving unread messages",
mock.initConverse( mock.initConverse(
null, ['rosterGroupsFetched', 'chatBoxesFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched', 'emojisInitialized'], {},
async function (done, _converse) { async function (done, _converse) {
await test_utils.waitForRoster(_converse, 'current', 1); await test_utils.waitForRoster(_converse, 'current', 1);
...@@ -1588,7 +1586,7 @@ ...@@ -1588,7 +1586,7 @@
it("is incremented when message is received and windows is not focused", it("is incremented when message is received and windows is not focused",
mock.initConverse( mock.initConverse(
null, ['rosterGroupsFetched', 'chatBoxesFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched', 'emojisInitialized'], {},
async function (done, _converse) { async function (done, _converse) {
await test_utils.waitForRoster(_converse, 'current', 1); await test_utils.waitForRoster(_converse, 'current', 1);
...@@ -1638,3 +1636,4 @@ ...@@ -1638,3 +1636,4 @@
}); });
}); });
})); }));
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
it("can be used to add contact and it checks for case-sensivity", it("can be used to add contact and it checks for case-sensivity",
mock.initConverse( mock.initConverse(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'emojisInitialized'], {},
async function (done, _converse) { async function (done, _converse) {
spyOn(_converse.api, "trigger").and.callThrough(); spyOn(_converse.api, "trigger").and.callThrough();
......
...@@ -461,7 +461,11 @@ ...@@ -461,7 +461,11 @@
done(); done();
})); }));
it("shows an error message if the file is too large", mock.initConverse(async (done, _converse) => { it("shows an error message if the file is too large",
mock.initConverse(
null, ['emojisInitialized'], {},
async function (done, _converse) {
const IQ_stanzas = _converse.connection.IQ_stanzas; const IQ_stanzas = _converse.connection.IQ_stanzas;
const IQ_ids = _converse.connection.IQ_ids; const IQ_ids = _converse.connection.IQ_ids;
const send_backup = XMLHttpRequest.prototype.send; const send_backup = XMLHttpRequest.prototype.send;
......
...@@ -927,7 +927,7 @@ ...@@ -927,7 +927,7 @@
it("will display larger if it's a single emoji", it("will display larger if it's a single emoji",
mock.initConverse( mock.initConverse(
null, ['rosterGroupsFetched', 'chatBoxesFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched', 'emojisInitialized'], {},
async function (done, _converse) { async function (done, _converse) {
await test_utils.waitForRoster(_converse, 'current'); await test_utils.waitForRoster(_converse, 'current');
...@@ -936,7 +936,7 @@ ...@@ -936,7 +936,7 @@
'from': sender_jid, 'from': sender_jid,
'to': _converse.connection.jid, 'to': _converse.connection.jid,
'type': 'chat', 'type': 'chat',
'id': (new Date()).getTime() 'id': _converse.connection.getUniqueId()
}).c('body').t('😇').up() }).c('body').t('😇').up()
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree()); .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree());
await new Promise(resolve => _converse.on('chatBoxInitialized', resolve)); await new Promise(resolve => _converse.on('chatBoxInitialized', resolve));
...@@ -944,8 +944,20 @@ ...@@ -944,8 +944,20 @@
await new Promise((resolve, reject) => view.once('messageInserted', resolve)); await new Promise((resolve, reject) => view.once('messageInserted', resolve));
const chat_content = view.el.querySelector('.chat-content'); const chat_content = view.el.querySelector('.chat-content');
const message = chat_content.querySelector('.chat-msg__text'); let message = chat_content.querySelector('.chat-msg__text');
expect(u.hasClass('chat-msg__text--larger', message)).toBe(true); expect(u.hasClass('chat-msg__text--larger', message)).toBe(true);
_converse.chatboxes.onMessage($msg({
'from': sender_jid,
'to': _converse.connection.jid,
'type': 'chat',
'id': _converse.connection.getUniqueId()
}).c('body').t('😇 Hello world! 😇 😇').up()
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree());
debugger;
await new Promise((resolve, reject) => view.once('messageInserted', resolve));
message = chat_content.querySelector('.message:last-child .chat-msg__text');
expect(u.hasClass('chat-msg__text--larger', message)).toBe(false);
done(); done();
})); }));
...@@ -990,7 +1002,7 @@ ...@@ -990,7 +1002,7 @@
it("will render images from their URLs", it("will render images from their URLs",
mock.initConverse( mock.initConverse(
null, ['rosterGroupsFetched', 'chatBoxesFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched', 'emojisInitialized'], {},
async function (done, _converse) { async function (done, _converse) {
await test_utils.waitForRoster(_converse, 'current'); await test_utils.waitForRoster(_converse, 'current');
...@@ -1038,7 +1050,7 @@ ...@@ -1038,7 +1050,7 @@
it("will render the message time as configured", it("will render the message time as configured",
mock.initConverse( mock.initConverse(
null, ['rosterGroupsFetched', 'chatBoxesFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched', 'emojisInitialized'], {},
async function (done, _converse) { async function (done, _converse) {
await test_utils.waitForRoster(_converse, 'current'); await test_utils.waitForRoster(_converse, 'current');
...@@ -1064,7 +1076,7 @@ ...@@ -1064,7 +1076,7 @@
it("will be correctly identified and rendered as a followup message", it("will be correctly identified and rendered as a followup message",
mock.initConverse( mock.initConverse(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'emojisInitialized'], {},
async function (done, _converse) { async function (done, _converse) {
await test_utils.waitForRoster(_converse, 'current'); await test_utils.waitForRoster(_converse, 'current');
...@@ -1422,7 +1434,7 @@ ...@@ -1422,7 +1434,7 @@
it("will open a chatbox and be displayed inside it", it("will open a chatbox and be displayed inside it",
mock.initConverse( mock.initConverse(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'emojisInitialized'], {},
async function (done, _converse) { async function (done, _converse) {
const include_nick = false; const include_nick = false;
...@@ -1468,7 +1480,7 @@ ...@@ -1468,7 +1480,7 @@
it("will be trimmed of leading and trailing whitespace", it("will be trimmed of leading and trailing whitespace",
mock.initConverse( mock.initConverse(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'emojisInitialized'], {},
async function (done, _converse) { async function (done, _converse) {
await test_utils.waitForRoster(_converse, 'current', 1, false); await test_utils.waitForRoster(_converse, 'current', 1, false);
...@@ -1683,7 +1695,7 @@ ...@@ -1683,7 +1695,7 @@
it("will have the error message displayed after itself", it("will have the error message displayed after itself",
mock.initConverse( mock.initConverse(
null, ['rosterGroupsFetched', 'chatBoxesFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched', 'emojisInitialized'], {},
async function (done, _converse) { async function (done, _converse) {
await test_utils.waitForRoster(_converse, 'current', 1); await test_utils.waitForRoster(_converse, 'current', 1);
...@@ -1736,7 +1748,7 @@ ...@@ -1736,7 +1748,7 @@
'message': msg_text 'message': msg_text
}); });
view.model.sendMessage(msg_text); view.model.sendMessage(msg_text);
await new Promise((resolve, reject) => view.once('messageInserted', resolve)); await u.waitUntil(() => sizzle('.chat-msg .chat-msg__text', chat_content).length === 5);
msg_txt = sizzle('.chat-msg:last .chat-msg__text', chat_content).pop().textContent; msg_txt = sizzle('.chat-msg:last .chat-msg__text', chat_content).pop().textContent;
expect(msg_txt).toEqual(msg_text); expect(msg_txt).toEqual(msg_text);
...@@ -1921,7 +1933,7 @@ ...@@ -1921,7 +1933,7 @@
it("is ignored if it's intended for a different resource and filter_by_resource is set to true", it("is ignored if it's intended for a different resource and filter_by_resource is set to true",
mock.initConverse( mock.initConverse(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'emojisInitialized'], {},
async function (done, _converse) { async function (done, _converse) {
await test_utils.waitForRoster(_converse, 'current'); await test_utils.waitForRoster(_converse, 'current');
...@@ -1959,8 +1971,8 @@ ...@@ -1959,8 +1971,8 @@
const view = _converse.chatboxviews.get(sender_jid); const view = _converse.chatboxviews.get(sender_jid);
await u.waitUntil(() => view.model.messages.length); await u.waitUntil(() => view.model.messages.length);
expect(_converse.chatboxes.getChatBox).toHaveBeenCalled(); expect(_converse.chatboxes.getChatBox).toHaveBeenCalled();
const chat_content = sizzle('.chat-content:last', view.el).pop(); const last_message = await u.waitUntil(() => sizzle('.chat-content:last .chat-msg__text', view.el).pop());
const msg_txt = chat_content.querySelector('.chat-msg .chat-msg__text').textContent; const msg_txt = last_message.textContent;
expect(msg_txt).toEqual(message); expect(msg_txt).toEqual(message);
done(); done();
})); }));
...@@ -2174,7 +2186,7 @@ ...@@ -2174,7 +2186,7 @@
it("is not sent when a markable message is received from someone not on the roster", it("is not sent when a markable message is received from someone not on the roster",
mock.initConverse( mock.initConverse(
null, ['rosterGroupsFetched'], {'allow_non_roster_messaging': true}, null, ['rosterGroupsFetched', 'emojisInitialized'], {'allow_non_roster_messaging': true},
async function (done, _converse) { async function (done, _converse) {
_converse.api.trigger('rosterContactsFetched'); _converse.api.trigger('rosterContactsFetched');
......
...@@ -264,7 +264,7 @@ ...@@ -264,7 +264,7 @@
it("will be created when muc_instant_rooms is set to true", it("will be created when muc_instant_rooms is set to true",
mock.initConverse( mock.initConverse(
null, ['rosterGroupsFetched', 'chatBoxesFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched', 'emojisInitialized'], {},
async function (done, _converse) { async function (done, _converse) {
const IQ_stanzas = _converse.connection.IQ_stanzas; const IQ_stanzas = _converse.connection.IQ_stanzas;
...@@ -555,7 +555,7 @@ ...@@ -555,7 +555,7 @@
it("is opened when an xmpp: URI is clicked inside another groupchat", it("is opened when an xmpp: URI is clicked inside another groupchat",
mock.initConverse( mock.initConverse(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'emojisInitialized'], {},
async function (done, _converse) { async function (done, _converse) {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
...@@ -584,7 +584,7 @@ ...@@ -584,7 +584,7 @@
it("shows a notification if it's not anonymous", it("shows a notification if it's not anonymous",
mock.initConverse( mock.initConverse(
null, ['rosterGroupsFetched', 'chatBoxesFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched', 'emojisInitialized'], {},
async function (done, _converse) { async function (done, _converse) {
const sent_IQs = _converse.connection.IQ_stanzas; const sent_IQs = _converse.connection.IQ_stanzas;
...@@ -1705,7 +1705,7 @@ ...@@ -1705,7 +1705,7 @@
it("shows users currently present in the groupchat", it("shows users currently present in the groupchat",
mock.initConverse( mock.initConverse(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'emojisInitialized'], {},
async function (done, _converse) { async function (done, _converse) {
await test_utils.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'romeo'); await test_utils.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'romeo');
...@@ -2242,7 +2242,7 @@ ...@@ -2242,7 +2242,7 @@
it("escapes the subject before rendering it, to avoid JS-injection attacks", it("escapes the subject before rendering it, to avoid JS-injection attacks",
mock.initConverse( mock.initConverse(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'emojisInitialized'], {},
async function (done, _converse) { async function (done, _converse) {
await test_utils.openAndEnterChatRoom(_converse, 'jdev@conference.jabber.org', 'jc'); await test_utils.openAndEnterChatRoom(_converse, 'jdev@conference.jabber.org', 'jc');
...@@ -2766,7 +2766,7 @@ ...@@ -2766,7 +2766,7 @@
it("informs users if they have been kicked out of the groupchat", it("informs users if they have been kicked out of the groupchat",
mock.initConverse( mock.initConverse(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'emojisInitialized'], {},
async function (done, _converse) { async function (done, _converse) {
/* <presence /* <presence
...@@ -3491,7 +3491,7 @@ ...@@ -3491,7 +3491,7 @@
it("takes a /kick command to kick a user", it("takes a /kick command to kick a user",
mock.initConverse( mock.initConverse(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'emojisInitialized'], {},
async function (done, _converse) { async function (done, _converse) {
let sent_IQ, IQ_id; let sent_IQ, IQ_id;
...@@ -3933,7 +3933,7 @@ ...@@ -3933,7 +3933,7 @@
it("will show an error message if the groupchat requires a password", it("will show an error message if the groupchat requires a password",
mock.initConverse( mock.initConverse(
null, ['rosterGroupsFetched', 'chatBoxesFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched', 'emojisInitialized'], {},
async function (done, _converse) { async function (done, _converse) {
const muc_jid = 'protected'; const muc_jid = 'protected';
...@@ -4723,7 +4723,7 @@ ...@@ -4723,7 +4723,7 @@
it("can be opened from a link in the \"Groupchats\" section of the controlbox", it("can be opened from a link in the \"Groupchats\" section of the controlbox",
mock.initConverse( mock.initConverse(
null, ['rosterGroupsFetched', 'chatBoxesFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched', 'emojisInitialized'], {},
async function (done, _converse) { async function (done, _converse) {
test_utils.openControlBox(); test_utils.openControlBox();
...@@ -4867,7 +4867,7 @@ ...@@ -4867,7 +4867,7 @@
it("shows the number of unread mentions received", it("shows the number of unread mentions received",
mock.initConverse( mock.initConverse(
null, ['rosterGroupsFetched'], {'allow_bookmarks': false}, null, ['rosterGroupsFetched', 'emojisInitialized'], {'allow_bookmarks': false},
async function (done, _converse) { async function (done, _converse) {
test_utils.openControlBox(); test_utils.openControlBox();
...@@ -4878,6 +4878,7 @@ ...@@ -4878,6 +4878,7 @@
const message = 'fires: Your attention is required'; const message = 'fires: Your attention is required';
await test_utils.openAndEnterChatRoom(_converse, muc_jid, 'fires'); await test_utils.openAndEnterChatRoom(_converse, muc_jid, 'fires');
const view = _converse.api.chatviews.get(muc_jid); const view = _converse.api.chatviews.get(muc_jid);
await u.waitUntil(() => roomspanel.el.querySelectorAll('.available-room').length);
expect(roomspanel.el.querySelectorAll('.available-room').length).toBe(1); expect(roomspanel.el.querySelectorAll('.available-room').length).toBe(1);
expect(roomspanel.el.querySelectorAll('.msgs-indicator').length).toBe(0); expect(roomspanel.el.querySelectorAll('.msgs-indicator').length).toBe(0);
......
...@@ -94,7 +94,7 @@ ...@@ -94,7 +94,7 @@
it("enables encrypted messages to be sent and received", it("enables encrypted messages to be sent and received",
mock.initConverse( mock.initConverse(
null, ['rosterGroupsFetched', 'chatBoxesFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched', 'emojisInitialized'], {},
async function (done, _converse) { async function (done, _converse) {
let sent_stanza; let sent_stanza;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
describe("A list of open groupchats", function () { describe("A list of open groupchats", function () {
it("is shown in controlbox", mock.initConverse( it("is shown in controlbox", mock.initConverse(
null, ['rosterGroupsFetched', 'chatBoxesFetched'], null, ['rosterGroupsFetched', 'chatBoxesFetched', 'emojisInitialized'],
{ allow_bookmarks: false // Makes testing easier, otherwise we { allow_bookmarks: false // Makes testing easier, otherwise we
// have to mock stanza traffic. // have to mock stanza traffic.
}, async function (done, _converse) { }, async function (done, _converse) {
...@@ -53,7 +53,9 @@ ...@@ -53,7 +53,9 @@
it("uses bookmarks to determine groupchat names", it("uses bookmarks to determine groupchat names",
mock.initConverse( mock.initConverse(
{'connection': ['send']}, ['rosterGroupsFetched', 'chatBoxesFetched'], {'view_mode': 'fullscreen'}, {'connection': ['send']},
['rosterGroupsFetched', 'chatBoxesFetched', 'emojisInitialized'],
{'view_mode': 'fullscreen'},
async function (done, _converse) { async function (done, _converse) {
await test_utils.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'romeo'); await test_utils.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'romeo');
...@@ -148,7 +150,7 @@ ...@@ -148,7 +150,7 @@
})); }));
it("has an info icon which opens a details modal when clicked", mock.initConverse( it("has an info icon which opens a details modal when clicked", mock.initConverse(
null, ['rosterGroupsFetched', 'chatBoxesFetched'], null, ['rosterGroupsFetched', 'chatBoxesFetched', 'emojisInitialized'],
{ whitelisted_plugins: ['converse-roomslist'], { whitelisted_plugins: ['converse-roomslist'],
allow_bookmarks: false // Makes testing easier, otherwise we allow_bookmarks: false // Makes testing easier, otherwise we
// have to mock stanza traffic. // have to mock stanza traffic.
...@@ -256,7 +258,7 @@ ...@@ -256,7 +258,7 @@
})); }));
it("can be closed", mock.initConverse( it("can be closed", mock.initConverse(
null, ['rosterGroupsFetched'], null, ['rosterGroupsFetched', 'emojisInitialized'],
{ whitelisted_plugins: ['converse-roomslist'], { whitelisted_plugins: ['converse-roomslist'],
allow_bookmarks: false // Makes testing easier, otherwise we have to mock stanza traffic. allow_bookmarks: false // Makes testing easier, otherwise we have to mock stanza traffic.
}, },
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
it("can be used to remove a contact", it("can be used to remove a contact",
mock.initConverse( mock.initConverse(
null, ['rosterGroupsFetched', 'chatBoxesFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched', 'emojisInitialized'], {},
async function (done, _converse) { async function (done, _converse) {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
...@@ -49,7 +49,7 @@ ...@@ -49,7 +49,7 @@
it("shows an alert when an error happened while removing the contact", it("shows an alert when an error happened while removing the contact",
mock.initConverse( mock.initConverse(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched', 'emojisInitialized'], {},
async function (done, _converse) { async function (done, _converse) {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
/** /**
* @module converse-chatview * @module converse-chatview
*/ */
import "@converse/headless/converse-emoji";
import "backbone.nativeview"; import "backbone.nativeview";
import "converse-chatboxviews"; import "converse-chatboxviews";
import "converse-message-view"; import "converse-message-view";
...@@ -30,10 +31,10 @@ import tpl_status_message from "templates/status_message.html"; ...@@ -30,10 +31,10 @@ import tpl_status_message from "templates/status_message.html";
import tpl_toolbar from "templates/toolbar.html"; import tpl_toolbar from "templates/toolbar.html";
import tpl_toolbar_fileupload from "templates/toolbar_fileupload.html"; import tpl_toolbar_fileupload from "templates/toolbar_fileupload.html";
import tpl_user_details_modal from "templates/user_details_modal.html"; import tpl_user_details_modal from "templates/user_details_modal.html";
import u from "@converse/headless/utils/emoji";
import xss from "xss/dist/xss"; import xss from "xss/dist/xss";
const { $msg, Backbone, Promise, Strophe, _, sizzle, dayjs } = converse.env; const { $msg, Backbone, Promise, Strophe, _, sizzle, dayjs } = converse.env;
const u = converse.env.utils;
converse.plugins.add('converse-chatview', { converse.plugins.add('converse-chatview', {
...@@ -47,15 +48,20 @@ converse.plugins.add('converse-chatview', { ...@@ -47,15 +48,20 @@ converse.plugins.add('converse-chatview', {
* *
* NB: These plugins need to have already been loaded via require.js. * NB: These plugins need to have already been loaded via require.js.
*/ */
dependencies: ["converse-chatboxviews", "converse-disco", "converse-message-view", "converse-modal"], dependencies: [
"converse-emoji",
"converse-chatboxviews",
"converse-disco",
"converse-message-view",
"converse-modal"
],
initialize () { initialize () {
/* The initialize function gets called as soon as the plugin is /* The initialize function gets called as soon as the plugin is
* loaded by converse.js's plugin machinery. * loaded by converse.js's plugin machinery.
*/ */
const { _converse } = this, const { _converse } = this;
{ __ } = _converse; const { __ } = _converse;
_converse.api.settings.update({ _converse.api.settings.update({
'auto_focus': true, 'auto_focus': true,
...@@ -105,20 +111,24 @@ converse.plugins.add('converse-chatview', { ...@@ -105,20 +111,24 @@ converse.plugins.add('converse-chatview', {
initialize () { initialize () {
this.model.on('change:current_skintone', this.render, this); this.model.on('change:current_skintone', this.render, this);
this.model.on('change:current_category', this.render, this); this.model.on('change:current_category', this.render, this);
_converse.api.trigger('emojiPickerViewInitialized');
}, },
toHTML () { toHTML () {
return tpl_emojis( const html = tpl_emojis(
Object.assign( Object.assign(
this.model.toJSON(), { this.model.toJSON(), {
'_': _, '_': _,
'transform': u.getEmojiRenderer(_converse), 'emoji_categories': _converse.emojis.categories,
'emojis_by_category': u.getEmojisByCategory(_converse), 'emojis_by_category': _converse.emojis.by_category,
'toned_emojis': u.getTonedEmojis(_converse), 'shouldBeHidden': this.shouldBeHidden,
'skintones': ['tone1', 'tone2', 'tone3', 'tone4', 'tone5'], 'skintones': ['tone1', 'tone2', 'tone3', 'tone4', 'tone5'],
'shouldBeHidden': this.shouldBeHidden 'toned_emojis': _converse.emojis.toned,
'transform': u.getEmojiRenderer()
} }
)); )
);
return html;
}, },
shouldBeHidden (shortname, current_skintone, toned_emojis) { shouldBeHidden (shortname, current_skintone, toned_emojis) {
...@@ -339,7 +349,7 @@ converse.plugins.add('converse-chatview', { ...@@ -339,7 +349,7 @@ converse.plugins.add('converse-chatview', {
'drop .chat-textarea': 'onDrop', 'drop .chat-textarea': 'onDrop',
}, },
initialize () { async initialize () {
this.initDebounced(); this.initDebounced();
this.model.messages.on('add', this.onMessageAdded, this); this.model.messages.on('add', this.onMessageAdded, this);
this.model.messages.on('rendered', this.scrollDown, this); this.model.messages.on('rendered', this.scrollDown, this);
...@@ -353,7 +363,11 @@ converse.plugins.add('converse-chatview', { ...@@ -353,7 +363,11 @@ converse.plugins.add('converse-chatview', {
this.model.presence.on('change:show', this.onPresenceChanged, this); this.model.presence.on('change:show', this.onPresenceChanged, this);
this.render(); this.render();
this.updateAfterMessagesFetched(); this.createEmojiPicker();
this.insertEmojiPicker();
await this.renderEmojiPicker();
await this.updateAfterMessagesFetched();
/** /**
* Triggered once the {@link _converse.ChatBoxView} has been initialized * Triggered once the {@link _converse.ChatBoxView} has been initialized
* @event _converse#chatBoxInitialized * @event _converse#chatBoxInitialized
...@@ -1139,9 +1153,7 @@ converse.plugins.add('converse-chatview', { ...@@ -1139,9 +1153,7 @@ converse.plugins.add('converse-chatview', {
_converse.emojipicker.browserStorage = new BrowserStorage[storage](id); _converse.emojipicker.browserStorage = new BrowserStorage[storage](id);
_converse.emojipicker.fetch(); _converse.emojipicker.fetch();
} }
this.emoji_picker_view = new _converse.EmojiPickerView({ this.emoji_picker_view = new _converse.EmojiPickerView({'model': _converse.emojipicker});
'model': _converse.emojipicker
});
}, },
insertEmoji (ev) { insertEmoji (ev) {
...@@ -1154,9 +1166,6 @@ converse.plugins.add('converse-chatview', { ...@@ -1154,9 +1166,6 @@ converse.plugins.add('converse-chatview', {
toggleEmojiMenu (ev) { toggleEmojiMenu (ev) {
if (this.emoji_dropdown === undefined) { if (this.emoji_dropdown === undefined) {
ev.stopPropagation(); ev.stopPropagation();
this.createEmojiPicker();
this.insertEmojiPicker();
this.renderEmojiPicker();
const dropdown_el = this.el.querySelector('.toggle-smiley.dropup'); const dropdown_el = this.el.querySelector('.toggle-smiley.dropup');
this.emoji_dropdown = new bootstrap.Dropdown(dropdown_el, true); this.emoji_dropdown = new bootstrap.Dropdown(dropdown_el, true);
...@@ -1262,12 +1271,13 @@ converse.plugins.add('converse-chatview', { ...@@ -1262,12 +1271,13 @@ converse.plugins.add('converse-chatview', {
return this; return this;
}, },
renderEmojiPicker () { async renderEmojiPicker () {
await _converse.api.waitUntil('emojisInitialized');
this.emoji_picker_view.render(); this.emoji_picker_view.render();
}, },
insertEmojiPicker () { insertEmojiPicker () {
var picker_el = this.el.querySelector('.emoji-picker'); const picker_el = this.el.querySelector('.emoji-picker');
if (picker_el !== null) { if (picker_el !== null) {
picker_el.innerHTML = ''; picker_el.innerHTML = '';
picker_el.appendChild(this.emoji_picker_view.el); picker_el.appendChild(this.emoji_picker_view.el);
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
/** /**
* @module converse-message-view * @module converse-message-view
*/ */
import "@converse/headless/converse-emoji";
import URI from "urijs"; import URI from "urijs";
import converse from "@converse/headless/converse-core"; import converse from "@converse/headless/converse-core";
import { debounce } from 'lodash' import { debounce } from 'lodash'
...@@ -17,10 +18,10 @@ import tpl_info from "templates/info.html"; ...@@ -17,10 +18,10 @@ import tpl_info from "templates/info.html";
import tpl_message from "templates/message.html"; import tpl_message from "templates/message.html";
import tpl_message_versions_modal from "templates/message_versions_modal.html"; import tpl_message_versions_modal from "templates/message_versions_modal.html";
import tpl_spinner from "templates/spinner.html"; import tpl_spinner from "templates/spinner.html";
import u from "@converse/headless/utils/emoji";
import xss from "xss/dist/xss"; import xss from "xss/dist/xss";
const { Backbone, dayjs } = converse.env; const { Backbone, dayjs } = converse.env;
const u = converse.env.utils;
converse.plugins.add('converse-message-view', { converse.plugins.add('converse-message-view', {
...@@ -223,7 +224,7 @@ converse.plugins.add('converse-message-view', { ...@@ -223,7 +224,7 @@ converse.plugins.add('converse-message-view', {
text = u.addMentionsMarkup(text, this.model.get('references'), this.model.collection.chatbox); text = u.addMentionsMarkup(text, this.model.get('references'), this.model.collection.chatbox);
text = u.addHyperlinks(text); text = u.addHyperlinks(text);
text = u.renderNewLines(text); text = u.renderNewLines(text);
text = u.addEmoji(_converse, text); text = u.addEmoji(text);
/** /**
* Synchronous event which provides a hook for transforming a chat message's body text * Synchronous event which provides a hook for transforming a chat message's body text
* after the default transformations have been applied. * after the default transformations have been applied.
...@@ -237,7 +238,7 @@ converse.plugins.add('converse-message-view', { ...@@ -237,7 +238,7 @@ converse.plugins.add('converse-message-view', {
}, },
async renderChatMessage () { async renderChatMessage () {
const is_me_message = this.model.isMeCommand(); await _converse.api.waitUntil('emojisInitialized');
const time = dayjs(this.model.get('time')); const time = dayjs(this.model.get('time'));
const role = this.model.vcard ? this.model.vcard.get('role') : null; const role = this.model.vcard ? this.model.vcard.get('role') : null;
const roles = role ? role.split(',') : []; const roles = role ? role.split(',') : [];
...@@ -248,7 +249,7 @@ converse.plugins.add('converse-message-view', { ...@@ -248,7 +249,7 @@ converse.plugins.add('converse-message-view', {
'__': __, '__': __,
'is_groupchat_message': this.model.get('type') === 'groupchat', 'is_groupchat_message': this.model.get('type') === 'groupchat',
'occupant': this.model.occupant, 'occupant': this.model.occupant,
'is_me_message': is_me_message, 'is_me_message': this.model.isMeCommand(),
'roles': roles, 'roles': roles,
'pretty_time': time.format(_converse.time_format), 'pretty_time': time.format(_converse.time_format),
'time': time.toISOString(), 'time': time.toISOString(),
......
...@@ -635,7 +635,7 @@ converse.plugins.add('converse-muc-views', { ...@@ -635,7 +635,7 @@ converse.plugins.add('converse-muc-views', {
'drop .chat-textarea': 'onDrop', 'drop .chat-textarea': 'onDrop',
}, },
initialize () { async initialize () {
this.initDebounced(); this.initDebounced();
this.model.messages.on('add', this.onMessageAdded, this); this.model.messages.on('add', this.onMessageAdded, this);
...@@ -661,8 +661,10 @@ converse.plugins.add('converse-muc-views', { ...@@ -661,8 +661,10 @@ converse.plugins.add('converse-muc-views', {
this.model.occupants.on('change:role', this.onOccupantRoleChanged, this); this.model.occupants.on('change:role', this.onOccupantRoleChanged, this);
this.model.occupants.on('change:affiliation', this.onOccupantAffiliationChanged, this); this.model.occupants.on('change:affiliation', this.onOccupantAffiliationChanged, this);
this.createEmojiPicker();
this.render(); this.render();
this.createEmojiPicker();
this.insertEmojiPicker();
await this.renderEmojiPicker();
this.updateAfterMessagesFetched(); this.updateAfterMessagesFetched();
this.createOccupantsView(); this.createOccupantsView();
this.onConnectionStatusChanged(); this.onConnectionStatusChanged();
...@@ -875,7 +877,6 @@ converse.plugins.add('converse-muc-views', { ...@@ -875,7 +877,6 @@ converse.plugins.add('converse-muc-views', {
this.model.save(); this.model.save();
} }
this.scrollDown(); this.scrollDown();
this.renderEmojiPicker();
}, },
onConnectionStatusChanged () { onConnectionStatusChanged () {
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
/** /**
* @module converse-chatboxes * @module converse-chatboxes
*/ */
import "./utils/emoji"; import "./converse-emoji";
import "./utils/form"; import "./utils/form";
import BrowserStorage from "backbone.browserStorage"; import BrowserStorage from "backbone.browserStorage";
import converse from "./converse-core"; import converse from "./converse-core";
...@@ -23,7 +23,7 @@ Strophe.addNamespace('MARKERS', 'urn:xmpp:chat-markers:0'); ...@@ -23,7 +23,7 @@ Strophe.addNamespace('MARKERS', 'urn:xmpp:chat-markers:0');
converse.plugins.add('converse-chatboxes', { converse.plugins.add('converse-chatboxes', {
dependencies: ["converse-roster", "converse-vcard"], dependencies: ["converse-emoji", "converse-roster", "converse-vcard"],
initialize () { initialize () {
/* The initialize function gets called as soon as the plugin is /* The initialize function gets called as soon as the plugin is
...@@ -946,7 +946,7 @@ converse.plugins.add('converse-chatboxes', { ...@@ -946,7 +946,7 @@ converse.plugins.add('converse-chatboxes', {
* @param { XMLElement } original_stanza - The original stanza, that contains the * @param { XMLElement } original_stanza - The original stanza, that contains the
* message stanza, if it was contained, otherwise it's the message stanza itself. * message stanza, if it was contained, otherwise it's the message stanza itself.
*/ */
getMessageAttributesFromStanza (stanza, original_stanza) { async getMessageAttributesFromStanza (stanza, original_stanza) {
const spoiler = sizzle(`spoiler[xmlns="${Strophe.NS.SPOILER}"]`, original_stanza).pop(); const spoiler = sizzle(`spoiler[xmlns="${Strophe.NS.SPOILER}"]`, original_stanza).pop();
const delay = sizzle(`delay[xmlns="${Strophe.NS.DELAY}"]`, original_stanza).pop(); const delay = sizzle(`delay[xmlns="${Strophe.NS.DELAY}"]`, original_stanza).pop();
const text = this.getMessageBody(stanza) || undefined; const text = this.getMessageBody(stanza) || undefined;
...@@ -956,6 +956,7 @@ converse.plugins.add('converse-chatboxes', { ...@@ -956,6 +956,7 @@ converse.plugins.add('converse-chatboxes', {
stanza.getElementsByTagName(_converse.ACTIVE).length && _converse.ACTIVE || stanza.getElementsByTagName(_converse.ACTIVE).length && _converse.ACTIVE ||
stanza.getElementsByTagName(_converse.GONE).length && _converse.GONE; stanza.getElementsByTagName(_converse.GONE).length && _converse.GONE;
const is_single_emoji = text ? await u.isSingleEmoji(text) : false;
const replaced_id = this.getReplaceId(stanza) const replaced_id = this.getReplaceId(stanza)
const msgid = replaced_id || stanza.getAttribute('id') || original_stanza.getAttribute('id'); const msgid = replaced_id || stanza.getAttribute('id') || original_stanza.getAttribute('id');
const attrs = Object.assign({ const attrs = Object.assign({
...@@ -963,7 +964,7 @@ converse.plugins.add('converse-chatboxes', { ...@@ -963,7 +964,7 @@ converse.plugins.add('converse-chatboxes', {
'is_archived': this.isArchived(original_stanza), 'is_archived': this.isArchived(original_stanza),
'is_delayed': !!delay, 'is_delayed': !!delay,
'is_spoiler': !!spoiler, 'is_spoiler': !!spoiler,
'is_single_emoji': text ? u.isSingleEmoji(text) : false, 'is_single_emoji': is_single_emoji,
'message': text, 'message': text,
'msgid': msgid, 'msgid': msgid,
'references': this.getReferencesFromStanza(stanza), 'references': this.getReferencesFromStanza(stanza),
...@@ -1087,7 +1088,7 @@ converse.plugins.add('converse-chatboxes', { ...@@ -1087,7 +1088,7 @@ converse.plugins.add('converse-chatboxes', {
collection.forEach(c => c.maybeShow()); collection.forEach(c => c.maybeShow());
/** /**
* Triggered when a message stanza is been received and processed. * Triggered when a message stanza is been received and processed.
* @event _converse#message * @event _converse#chatBoxesFetched
* @type { object } * @type { object }
* @property { _converse.ChatBox | _converse.ChatRoom } chatbox * @property { _converse.ChatBox | _converse.ChatRoom } chatbox
* @property { XMLElement } stanza * @property { XMLElement } stanza
......
...@@ -80,6 +80,7 @@ const CORE_PLUGINS = [ ...@@ -80,6 +80,7 @@ const CORE_PLUGINS = [
'converse-caps', 'converse-caps',
'converse-chatboxes', 'converse-chatboxes',
'converse-disco', 'converse-disco',
'converse-emoji',
'converse-mam', 'converse-mam',
'converse-muc', 'converse-muc',
'converse-ping', 'converse-ping',
......
This diff is collapsed.
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* Implements the non-view logic for XEP-0045 Multi-User Chat * Implements the non-view logic for XEP-0045 Multi-User Chat
*/ */
import "./converse-disco"; import "./converse-disco";
import "./utils/emoji"; import "./converse-emoji";
import "./utils/muc"; import "./utils/muc";
import BrowserStorage from "backbone.browserStorage"; import BrowserStorage from "backbone.browserStorage";
import converse from "./converse-core"; import converse from "./converse-core";
......
This source diff could not be displayed because it is too large. You can view the blob instead.
<div class="emoji-picker-container"> <div class="emoji-picker-container">
{[ o._.forEach(o.emojis_by_category, function (obj, category) { ]} {[ o.emoji_categories.forEach(function (category) { ]}
<ul class="emoji-picker emoji-picker-{{{category}}} {[ if (o.current_category !== category) { ]} hidden {[ } ]}"> <ul class="emoji-picker emoji-picker-{{{category}}} {[ if (o.current_category !== category) { ]} hidden {[ } ]}">
{[ o._.forEach(o.emojis_by_category[category], function (emoji) { ]} {[ o._.forEach(o.emojis_by_category[category], function (emoji) { ]}
<li class="emoji insert-emoji {[ if (o.shouldBeHidden(emoji._shortname, o.current_skintone, o.toned_emojis)) { ]} hidden {[ }; ]}" <li class="emoji insert-emoji {[ if (o.shouldBeHidden(emoji._shortname, o.current_skintone, o.toned_emojis)) { ]} hidden {[ }; ]}"
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
<ul class="emoji-toolbar"> <ul class="emoji-toolbar">
<li class="emoji-category-picker"> <li class="emoji-category-picker">
<ul> <ul>
{[ o._.forEach(o.emojis_by_category, function (obj, category) { ]} {[ o.emoji_categories.forEach(function (category) { ]}
<li data-category="{{{category}}}" class="emoji-category {[ if (o.current_category === category) { ]} picked {[ } ]}"> <li data-category="{{{category}}}" class="emoji-category {[ if (o.current_category === category) { ]} picked {[ } ]}">
<a class="pick-category" href="#" data-category="{{{category}}}"> {{ o.transform(o.emojis_by_category[category][0]._shortname) }} </a> <a class="pick-category" href="#" data-category="{{{category}}}"> {{ o.transform(o.emojis_by_category[category][0]._shortname) }} </a>
</li> </li>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment