replace emojione with twemoji. completely untested & debugged & unoptimised

This commit is contained in:
Matthew Hodgson 2019-05-19 15:23:43 +01:00
parent 7a244b85c1
commit dc72641264
30 changed files with 103 additions and 343 deletions

View file

@ -256,8 +256,6 @@ export default class Autocomplete extends React.Component {
}
render() {
const EmojiText = sdk.getComponent('views.elements.EmojiText');
let position = 1;
const renderedCompletions = this.state.completions.map((completionResult, i) => {
const completions = completionResult.completions.map((completion, i) => {
@ -282,7 +280,7 @@ export default class Autocomplete extends React.Component {
return completions.length > 0 ? (
<div key={i} className="mx_Autocomplete_ProviderSection">
<EmojiText element="div" className="mx_Autocomplete_provider_name">{ completionResult.provider.getName() }</EmojiText>
<div className="mx_Autocomplete_provider_name">{ completionResult.provider.getName() }</div>
{ completionResult.provider.renderCompletions(completions) }
</div>
) : null;

View file

@ -111,7 +111,6 @@ const EntityTile = React.createClass({
let nameEl;
const {name} = this.props;
const EmojiText = sdk.getComponent('elements.EmojiText');
if (!this.props.suppressOnHover) {
const activeAgo = this.props.presenceLastActiveAgo ?
(Date.now() - (this.props.presenceLastTs - this.props.presenceLastActiveAgo)) : -1;
@ -128,24 +127,24 @@ const EntityTile = React.createClass({
}
nameEl = (
<div className="mx_EntityTile_details">
<EmojiText element="div" className="mx_EntityTile_name" dir="auto">
<div className="mx_EntityTile_name" dir="auto">
{ name }
</EmojiText>
</div>
{presenceLabel}
</div>
);
} else if (this.props.subtextLabel) {
nameEl = (
<div className="mx_EntityTile_details">
<EmojiText element="div" className="mx_EntityTile_name" dir="auto">
<div className="mx_EntityTile_name" dir="auto">
{name}
</EmojiText>
</div>
<span className="mx_EntityTile_subtext">{this.props.subtextLabel}</span>
</div>
);
} else {
nameEl = (
<EmojiText element="div" className="mx_EntityTile_name" dir="auto">{ name }</EmojiText>
<div className="mx_EntityTile_name" dir="auto">{ name }</div>
);
}

View file

@ -674,14 +674,13 @@ module.exports = withMatrixClient(React.createClass({
switch (this.props.tileShape) {
case 'notif': {
const EmojiText = sdk.getComponent('elements.EmojiText');
const room = this.props.matrixClient.getRoom(this.props.mxEvent.getRoomId());
return (
<div className={classes}>
<div className="mx_EventTile_roomName">
<EmojiText element="a" href={permalink} onClick={this.onPermalinkClicked}>
<a href={permalink} onClick={this.onPermalinkClicked}>
{ room ? room.name : '' }
</EmojiText>
</a>
</div>
<div className="mx_EventTile_senderDetails">
{ avatar }

View file

@ -978,7 +978,6 @@ module.exports = withMatrixClient(React.createClass({
}
const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper");
const EmojiText = sdk.getComponent('elements.EmojiText');
let backButton;
if (this.props.member.roomId) {
@ -993,7 +992,7 @@ module.exports = withMatrixClient(React.createClass({
<div className="mx_MemberInfo_name">
{ backButton }
{ e2eIconElement }
<EmojiText element="h2">{ memberName }</EmojiText>
<h2>{ memberName }</h2>
</div>
{ avatarElement }
<div className="mx_MemberInfo_container">

View file

@ -51,10 +51,9 @@ import ContentMessages from '../../../ContentMessages';
import {MATRIXTO_URL_PATTERN} from '../../../linkify-matrix';
import {
asciiRegexp, unicodeRegexp, shortnameToUnicode,
asciiList, mapUnicodeToShort, toShort,
} from 'emojione';
import EMOJIBASE from 'emojibase-data/en/compact.json';
import EMOTICON_REGEX from 'emojibase-regex/emoticon';
import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
import {makeUserPermalink} from "../../../matrix-to";
import ReplyPreview from "./ReplyPreview";
@ -63,9 +62,7 @@ import ReplyThread from "../elements/ReplyThread";
import {ContentHelpers} from 'matrix-js-sdk';
import AccessibleButton from '../elements/AccessibleButton';
const EMOJI_UNICODE_TO_SHORTNAME = mapUnicodeToShort();
const REGEX_EMOJI_WHITESPACE = new RegExp('(?:^|\\s)(' + asciiRegexp + ')\\s$');
const EMOJI_REGEX = new RegExp(unicodeRegexp, 'g');
const REGEX_EMOJI_WHITESPACE = new RegExp('(?:^|\\s)(' + EMOTICON_REGEX + ')\\s$');
const TYPING_USER_TIMEOUT = 10000; const TYPING_SERVER_TIMEOUT = 30000;
@ -273,9 +270,8 @@ export default class MessageComposerInput extends React.Component {
case 'emoji':
// XXX: apparently you can't return plain strings from serializer rules
// until https://github.com/ianstormtaylor/slate/pull/1854 is merged.
// So instead we temporarily wrap emoji from RTE in an arbitrary tag
// (<b/>). <span/> would be nicer, but in practice it causes CSS issues.
return <b>{ obj.data.get('emojiUnicode') }</b>;
// So instead we temporarily wrap emoji from RTE in a span.
return <span>{ obj.data.get('emojiUnicode') }</span>;
}
return this.renderNode({
node: obj,
@ -375,7 +371,6 @@ export default class MessageComposerInput extends React.Component {
const html = HtmlUtils.bodyToHtml(payload.event.getContent(), null, {
forComposerQuote: true,
returnString: true,
emojiOne: false,
});
const fragment = this.html.deserialize(html);
// FIXME: do we want to put in a permalink to the original quote here?
@ -540,10 +535,7 @@ export default class MessageComposerInput extends React.Component {
// The first matched group includes just the matched plaintext emoji
const emojiMatch = REGEX_EMOJI_WHITESPACE.exec(text.slice(0, currentStartOffset));
if (emojiMatch) {
// plaintext -> hex unicode
const emojiUc = asciiList[emojiMatch[1]];
// hex unicode -> shortname -> actual unicode
const unicodeEmoji = shortnameToUnicode(EMOJI_UNICODE_TO_SHORTNAME[emojiUc]);
const unicodeEmoji = EMOJIBASE.find(e => e.emoticon && e.emoticon.contains(emoijMatch[1]));
const range = Range.create({
anchor: {
@ -561,54 +553,6 @@ export default class MessageComposerInput extends React.Component {
}
}
// emojioneify any emoji
let foundEmoji;
do {
foundEmoji = false;
for (const node of editorState.document.getTexts()) {
if (node.text !== '' && HtmlUtils.containsEmoji(node.text)) {
let match;
EMOJI_REGEX.lastIndex = 0;
while ((match = EMOJI_REGEX.exec(node.text)) !== null) {
const range = Range.create({
anchor: {
key: node.key,
offset: match.index,
},
focus: {
key: node.key,
offset: match.index + match[0].length,
},
});
const inline = Inline.create({
type: 'emoji',
data: { emojiUnicode: match[0] },
});
change = change.insertInlineAtRange(range, inline);
editorState = change.value;
// if we replaced an emoji, start again looking for more
// emoji in the new editor state since doing the replacement
// will change the node structure & offsets so we can't compute
// insertion ranges from node.key / match.index anymore.
foundEmoji = true;
break;
}
}
}
} while (foundEmoji);
// work around weird bug where inserting emoji via the macOS
// emoji picker can leave the selection stuck in the emoji's
// child text. This seems to happen due to selection getting
// moved in the normalisation phase after calculating these changes
if (editorState.selection.anchor.key &&
editorState.document.getParent(editorState.selection.anchor.key).type === 'emoji') {
change = change.moveToStartOfNextText();
editorState = change.value;
}
if (this.props.onInputStateChanged && editorState.blocks.size > 0) {
let blockType = editorState.blocks.first().type;
// console.log("onInputStateChanged; current block type is " + blockType + " and marks are " + editorState.activeMarks);
@ -1295,7 +1239,7 @@ export default class MessageComposerInput extends React.Component {
// Move selection to the end of the selected history
const change = editorState.change().moveToEndOfNode(editorState.document);
// We don't call this.onChange(change) now, as fixups on stuff like emoji
// We don't call this.onChange(change) now, as fixups on stuff like pills
// should already have been done and persisted in the history.
editorState = change.value;
@ -1473,20 +1417,8 @@ export default class MessageComposerInput extends React.Component {
</a>;
}
}
case 'emoji': {
const { data } = node;
const emojiUnicode = data.get('emojiUnicode');
const uri = RichText.unicodeToEmojiUri(emojiUnicode);
const shortname = toShort(emojiUnicode);
const className = classNames('mx_emojione', {
mx_emojione_selected: isSelected,
});
const style = {};
if (props.selected) style.border = '1px solid blue';
return <img className={ className } src={ uri }
title={ shortname } alt={ emojiUnicode } style={style}
/>;
}
case 'emoji':
return data.get('emojiUnicode');
}
};

View file

@ -66,13 +66,12 @@ export default class ReplyPreview extends React.Component {
if (!this.state.event) return null;
const EventTile = sdk.getComponent('rooms.EventTile');
const EmojiText = sdk.getComponent('views.elements.EmojiText');
return <div className="mx_ReplyPreview">
<div className="mx_ReplyPreview_section">
<EmojiText element="div" className="mx_ReplyPreview_header mx_ReplyPreview_title">
<div className="mx_ReplyPreview_header mx_ReplyPreview_title">
{ '💬 ' + _t('Replying') }
</EmojiText>
</div>
<div className="mx_ReplyPreview_header mx_ReplyPreview_cancel">
<img className="mx_filterFlipColor" src={require("../../../../res/img/cancel.svg")} width="18" height="18"
onClick={cancelQuoting} />

View file

@ -147,7 +147,6 @@ module.exports = React.createClass({
render: function() {
const RoomAvatar = sdk.getComponent("avatars.RoomAvatar");
const EmojiText = sdk.getComponent('elements.EmojiText');
let searchStatus = null;
let cancelButton = null;
@ -191,10 +190,10 @@ module.exports = React.createClass({
roomName = this.props.room.name;
}
const emojiTextClasses = classNames('mx_RoomHeader_nametext', { mx_RoomHeader_settingsHint: settingsHint });
const textClasses = classNames('mx_RoomHeader_nametext', { mx_RoomHeader_settingsHint: settingsHint });
const name =
<div className="mx_RoomHeader_name" onClick={this.props.onSettingsClick}>
<EmojiText dir="auto" element="div" className={emojiTextClasses} title={roomName}>{ roomName }</EmojiText>
<div dir="auto" className={textClasses} title={roomName}>{ roomName }</div>
{ searchStatus }
</div>;

View file

@ -342,7 +342,6 @@ module.exports = React.createClass({
badge = <div className={badgeClasses}>{ badgeContent }</div>;
}
const EmojiText = sdk.getComponent('elements.EmojiText');
let label;
let subtextLabel;
let tooltip;
@ -354,14 +353,7 @@ module.exports = React.createClass({
});
subtextLabel = subtext ? <span className="mx_RoomTile_subtext">{ subtext }</span> : null;
if (this.state.selected) {
const nameSelected = <EmojiText>{ name }</EmojiText>;
label = <div title={name} className={nameClasses} dir="auto">{ nameSelected }</div>;
} else {
label = <EmojiText element="div" title={name} className={nameClasses} dir="auto">{ name }</EmojiText>;
}
label = <div title={name} className={nameClasses} dir="auto">{ nameSelected }</div>;
} else if (this.state.hover) {
const Tooltip = sdk.getComponent("elements.Tooltip");
tooltip = <Tooltip className="mx_RoomTile_tooltip" label={this.props.room.name} dir="auto" />;

View file

@ -212,15 +212,13 @@ module.exports = React.createClass({
return (<div className="mx_WhoIsTypingTile_empty" />);
}
const EmojiText = sdk.getComponent('elements.EmojiText');
return (
<li className="mx_WhoIsTypingTile">
<div className="mx_WhoIsTypingTile_avatars">
{ this._renderTypingIndicatorAvatars(usersTyping, this.props.whoIsTypingLimit) }
</div>
<div className="mx_WhoIsTypingTile_label">
<EmojiText>{ typingString }</EmojiText>
{ typingString }
</div>
</li>
);