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