Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.

Commit 0273795

Browse files
committed
add transform step to composer to auto-replace emoticons with emoji
1 parent 4fd4ad4 commit 0273795

File tree

1 file changed

+30
-0
lines changed

1 file changed

+30
-0
lines changed

src/components/views/rooms/BasicMessageComposer.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ import {autoCompleteCreator} from '../../../editor/parts';
2525
import {renderModel} from '../../../editor/render';
2626
import {Room} from 'matrix-js-sdk';
2727
import TypingStore from "../../../stores/TypingStore";
28+
import EMOJIBASE from 'emojibase-data/en/compact.json';
29+
import SettingsStore from "../../../settings/SettingsStore";
30+
import EMOTICON_REGEX from 'emojibase-regex/emoticon';
31+
32+
const REGEX_EMOTICON_WHITESPACE = new RegExp('(?:^|\\s)(' + EMOTICON_REGEX.source + ')\\s$');
2833

2934
const IS_MAC = navigator.platform.indexOf("Mac") !== -1;
3035

@@ -70,6 +75,28 @@ export default class BasicMessageEditor extends React.Component {
7075
this._modifiedFlag = false;
7176
}
7277

78+
_replaceEmoticon = (caret, inputType, diff) => {
79+
const {model} = this.props;
80+
const range = model.startRange(caret);
81+
// expand range max 8 characters backwards from caret
82+
let n = 8;
83+
range.expandBackwardsWhile((index, offset) => {
84+
const part = model.parts[index];
85+
n -= 1;
86+
return n >= 0 && (part.type === "plain" || part.type === "pill-candidate");
87+
});
88+
const emoticonMatch = REGEX_EMOTICON_WHITESPACE.exec(range.text);
89+
if (emoticonMatch) {
90+
const query = emoticonMatch[1].toLowerCase().replace("-", "");
91+
const data = EMOJIBASE.find(e => e.emoticon ? e.emoticon.toLowerCase() === query : false);
92+
if (data) {
93+
// + 1 because index is reported without preceding space
94+
range.moveStart(emoticonMatch.index + 1);
95+
return range.replace([this.props.model.partCreator.plain(data.unicode + " ")]);
96+
}
97+
}
98+
}
99+
73100
_updateEditorState = (caret, inputType, diff) => {
74101
renderModel(this._editorRef, this.props.model);
75102
if (caret) {
@@ -262,6 +289,9 @@ export default class BasicMessageEditor extends React.Component {
262289
componentDidMount() {
263290
const model = this.props.model;
264291
model.setUpdateCallback(this._updateEditorState);
292+
if (SettingsStore.getValue('MessageComposerInput.autoReplaceEmoji')) {
293+
model.setTransformCallback(this._replaceEmoticon);
294+
}
265295
const partCreator = model.partCreator;
266296
// TODO: does this allow us to get rid of EditorStateTransfer?
267297
// not really, but we could not serialize the parts, and just change the autoCompleter

0 commit comments

Comments
 (0)