Various fixes and improvements to emojification.
- Use locally hosted emoji - Emojify SenderProfile and m.emote - Add emoji shortcodes as titles
This commit is contained in:
parent
4b8ad3c102
commit
dbbea63227
5 changed files with 83 additions and 6 deletions
|
@ -24,8 +24,39 @@ import escape from 'lodash/escape';
|
||||||
import emojione from 'emojione';
|
import emojione from 'emojione';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
emojione.imagePathSVG = 'emojione/svg/';
|
||||||
|
emojione.imageType = 'svg';
|
||||||
|
|
||||||
const EMOJI_REGEX = new RegExp(emojione.unicodeRegexp+"+", "gi");
|
const EMOJI_REGEX = new RegExp(emojione.unicodeRegexp+"+", "gi");
|
||||||
|
|
||||||
|
/* modified from https://github.com/Ranks/emojione/blob/master/lib/js/emojione.js
|
||||||
|
* because we want to include emoji shortnames in title text
|
||||||
|
*/
|
||||||
|
export function unicodeToImage(str) {
|
||||||
|
let replaceWith, unicode, alt;
|
||||||
|
const mappedUnicode = emojione.mapUnicodeToShort();
|
||||||
|
|
||||||
|
str = str.replace(emojione.regUnicode, function(unicodeChar) {
|
||||||
|
if ( (typeof unicodeChar === 'undefined') || (unicodeChar === '') || (!(unicodeChar in emojione.jsEscapeMap)) ) {
|
||||||
|
// if the unicodeChar doesnt exist just return the entire match
|
||||||
|
return unicodeChar;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// get the unicode codepoint from the actual char
|
||||||
|
unicode = emojione.jsEscapeMap[unicodeChar];
|
||||||
|
|
||||||
|
// depending on the settings, we'll either add the native unicode as the alt tag, otherwise the shortname
|
||||||
|
alt = (emojione.unicodeAlt) ? emojione.convert(unicode.toUpperCase()) : mappedUnicode[unicode];
|
||||||
|
const title = mappedUnicode[unicode];
|
||||||
|
|
||||||
|
replaceWith = `<img class="emojione" title="${title}" alt="${alt}" src="${emojione.imagePathSVG}${unicode}.svg${emojione.cacheBustParam}"/>`;
|
||||||
|
return replaceWith;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return str;
|
||||||
|
};
|
||||||
|
|
||||||
var sanitizeHtmlParams = {
|
var sanitizeHtmlParams = {
|
||||||
allowedTags: [
|
allowedTags: [
|
||||||
'font', // custom to matrix for IRC-style font coloring
|
'font', // custom to matrix for IRC-style font coloring
|
||||||
|
@ -211,8 +242,7 @@ module.exports = {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
safeBody = sanitizeHtml(body, sanitizeHtmlParams);
|
safeBody = sanitizeHtml(body, sanitizeHtmlParams);
|
||||||
emojione.imageType = 'svg';
|
safeBody = unicodeToImage(safeBody);
|
||||||
safeBody = emojione.unicodeToImage(safeBody);
|
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
delete sanitizeHtmlParams.textFilter;
|
delete sanitizeHtmlParams.textFilter;
|
||||||
|
@ -239,7 +269,6 @@ module.exports = {
|
||||||
},
|
},
|
||||||
|
|
||||||
emojifyText: function(text) {
|
emojifyText: function(text) {
|
||||||
emojione.imageType = 'svg';
|
|
||||||
return {
|
return {
|
||||||
__html: emojione.unicodeToImage(escape(text)),
|
__html: emojione.unicodeToImage(escape(text)),
|
||||||
};
|
};
|
||||||
|
|
|
@ -72,6 +72,7 @@ module.exports.components['views.messages.MFileBody'] = require('./components/vi
|
||||||
module.exports.components['views.messages.MImageBody'] = require('./components/views/messages/MImageBody');
|
module.exports.components['views.messages.MImageBody'] = require('./components/views/messages/MImageBody');
|
||||||
module.exports.components['views.messages.MVideoBody'] = require('./components/views/messages/MVideoBody');
|
module.exports.components['views.messages.MVideoBody'] = require('./components/views/messages/MVideoBody');
|
||||||
module.exports.components['views.messages.MessageEvent'] = require('./components/views/messages/MessageEvent');
|
module.exports.components['views.messages.MessageEvent'] = require('./components/views/messages/MessageEvent');
|
||||||
|
module.exports.components['views.messages.SenderProfile'] = require('./components/views/messages/SenderProfile');
|
||||||
module.exports.components['views.messages.TextualBody'] = require('./components/views/messages/TextualBody');
|
module.exports.components['views.messages.TextualBody'] = require('./components/views/messages/TextualBody');
|
||||||
module.exports.components['views.messages.TextualEvent'] = require('./components/views/messages/TextualEvent');
|
module.exports.components['views.messages.TextualEvent'] = require('./components/views/messages/TextualEvent');
|
||||||
module.exports.components['views.messages.UnknownBody'] = require('./components/views/messages/UnknownBody');
|
module.exports.components['views.messages.UnknownBody'] = require('./components/views/messages/UnknownBody');
|
||||||
|
|
|
@ -19,6 +19,7 @@ var sdk = require('../../index');
|
||||||
var dis = require("../../dispatcher");
|
var dis = require("../../dispatcher");
|
||||||
var WhoIsTyping = require("../../WhoIsTyping");
|
var WhoIsTyping = require("../../WhoIsTyping");
|
||||||
var MatrixClientPeg = require("../../MatrixClientPeg");
|
var MatrixClientPeg = require("../../MatrixClientPeg");
|
||||||
|
import {emojifyText} from '../../HtmlUtils';
|
||||||
|
|
||||||
module.exports = React.createClass({
|
module.exports = React.createClass({
|
||||||
displayName: 'RoomStatusBar',
|
displayName: 'RoomStatusBar',
|
||||||
|
@ -259,10 +260,11 @@ module.exports = React.createClass({
|
||||||
}
|
}
|
||||||
|
|
||||||
var typingString = this.state.whoisTypingString;
|
var typingString = this.state.whoisTypingString;
|
||||||
|
const typingHtml = emojifyText(typingString);
|
||||||
if (typingString) {
|
if (typingString) {
|
||||||
return (
|
return (
|
||||||
<div className="mx_RoomStatusBar_typingBar">
|
<div className="mx_RoomStatusBar_typingBar">
|
||||||
{typingString}
|
<span dangerouslySetInnerHTML={typingHtml} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
43
src/components/views/messages/SenderProfile.js
Normal file
43
src/components/views/messages/SenderProfile.js
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
Copyright 2015, 2016 OpenMarket Ltd
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import {emojifyText} from '../../../HtmlUtils';
|
||||||
|
|
||||||
|
export default function SenderProfile(props) {
|
||||||
|
const {mxEvent} = props;
|
||||||
|
const name = mxEvent.sender ? mxEvent.sender.name : mxEvent.getSender();
|
||||||
|
const {msgtype} = mxEvent.getContent();
|
||||||
|
|
||||||
|
if (msgtype === 'm.emote') {
|
||||||
|
return <span />; // emote message must include the name so don't duplicate it
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<span className="mx_SenderProfile"
|
||||||
|
dangerouslySetInnerHTML={emojifyText(`${name || ''} ${props.aux || ''}`)}
|
||||||
|
onClick={props.onClick}>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
SenderProfile.propTypes = {
|
||||||
|
mxEvent: React.PropTypes.object.isRequired, // event whose sender we're showing
|
||||||
|
aux: React.PropTypes.string, // stuff to go after the sender name, if anything
|
||||||
|
onClick: React.PropTypes.func,
|
||||||
|
};
|
|
@ -23,6 +23,7 @@ var linkify = require('linkifyjs');
|
||||||
var linkifyElement = require('linkifyjs/element');
|
var linkifyElement = require('linkifyjs/element');
|
||||||
var linkifyMatrix = require('../../../linkify-matrix');
|
var linkifyMatrix = require('../../../linkify-matrix');
|
||||||
var sdk = require('../../../index');
|
var sdk = require('../../../index');
|
||||||
|
import {emojifyText} from '../../../HtmlUtils';
|
||||||
|
|
||||||
linkifyMatrix(linkify);
|
linkifyMatrix(linkify);
|
||||||
|
|
||||||
|
@ -200,10 +201,11 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
switch (content.msgtype) {
|
switch (content.msgtype) {
|
||||||
case "m.emote":
|
case "m.emote":
|
||||||
var name = mxEvent.sender ? mxEvent.sender.name : mxEvent.getSender();
|
const name = mxEvent.sender ? mxEvent.sender.name : mxEvent.getSender();
|
||||||
|
const nameHtml = emojifyText(name);
|
||||||
return (
|
return (
|
||||||
<span ref="content" className="mx_MEmoteBody mx_EventTile_content">
|
<span ref="content" className="mx_MEmoteBody mx_EventTile_content">
|
||||||
* { name } { body }
|
* <span dangerouslySetInnerHTML={nameHtml} /> { body }
|
||||||
{ widgets }
|
{ widgets }
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue