mirror of
https://github.com/element-hq/element-web.git
synced 2024-12-16 13:31:32 +03:00
Replace emoji at the end of a message
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
This commit is contained in:
parent
e91f4b7eb2
commit
3edf05d38d
2 changed files with 16 additions and 6 deletions
|
@ -51,6 +51,7 @@ import {replaceableComponent} from "../../../utils/replaceableComponent";
|
||||||
|
|
||||||
// matches emoticons which follow the start of a line or whitespace
|
// matches emoticons which follow the start of a line or whitespace
|
||||||
const REGEX_EMOTICON_WHITESPACE = new RegExp('(?:^|\\s)(' + EMOTICON_REGEX.source + ')\\s$');
|
const REGEX_EMOTICON_WHITESPACE = new RegExp('(?:^|\\s)(' + EMOTICON_REGEX.source + ')\\s$');
|
||||||
|
export const REGEX_EMOTICON = new RegExp('(?:^|\\s)(' + EMOTICON_REGEX.source + ')$');
|
||||||
|
|
||||||
const IS_MAC = navigator.platform.indexOf("Mac") !== -1;
|
const IS_MAC = navigator.platform.indexOf("Mac") !== -1;
|
||||||
|
|
||||||
|
@ -150,7 +151,7 @@ export default class BasicMessageEditor extends React.Component<IProps, IState>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private replaceEmoticon = (caretPosition: DocumentPosition) => {
|
public replaceEmoticon(caretPosition: DocumentPosition, regex: RegExp) {
|
||||||
const {model} = this.props;
|
const {model} = this.props;
|
||||||
const range = model.startRange(caretPosition);
|
const range = model.startRange(caretPosition);
|
||||||
// expand range max 8 characters backwards from caretPosition,
|
// expand range max 8 characters backwards from caretPosition,
|
||||||
|
@ -161,7 +162,7 @@ export default class BasicMessageEditor extends React.Component<IProps, IState>
|
||||||
n -= 1;
|
n -= 1;
|
||||||
return n >= 0 && (part.type === "plain" || part.type === "pill-candidate");
|
return n >= 0 && (part.type === "plain" || part.type === "pill-candidate");
|
||||||
});
|
});
|
||||||
const emoticonMatch = REGEX_EMOTICON_WHITESPACE.exec(range.text);
|
const emoticonMatch = regex.exec(range.text);
|
||||||
if (emoticonMatch) {
|
if (emoticonMatch) {
|
||||||
const query = emoticonMatch[1].replace("-", "");
|
const query = emoticonMatch[1].replace("-", "");
|
||||||
// try both exact match and lower-case, this means that xd won't match xD but :P will match :p
|
// try both exact match and lower-case, this means that xd won't match xD but :P will match :p
|
||||||
|
@ -180,7 +181,7 @@ export default class BasicMessageEditor extends React.Component<IProps, IState>
|
||||||
return range.replace([partCreator.plain(data.unicode + " ")]);
|
return range.replace([partCreator.plain(data.unicode + " ")]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
private updateEditorState = (selection: Caret, inputType?: string, diff?: IDiff) => {
|
private updateEditorState = (selection: Caret, inputType?: string, diff?: IDiff) => {
|
||||||
renderModel(this.editorRef.current, this.props.model);
|
renderModel(this.editorRef.current, this.props.model);
|
||||||
|
@ -567,8 +568,7 @@ export default class BasicMessageEditor extends React.Component<IProps, IState>
|
||||||
};
|
};
|
||||||
|
|
||||||
private configureEmoticonAutoReplace = () => {
|
private configureEmoticonAutoReplace = () => {
|
||||||
const shouldReplace = SettingsStore.getValue('MessageComposerInput.autoReplaceEmoji');
|
this.props.model.setTransformCallback(this.transform);
|
||||||
this.props.model.setTransformCallback(shouldReplace ? this.replaceEmoticon : null);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private configureShouldShowPillAvatar = () => {
|
private configureShouldShowPillAvatar = () => {
|
||||||
|
@ -576,6 +576,11 @@ export default class BasicMessageEditor extends React.Component<IProps, IState>
|
||||||
this.setState({ showPillAvatar });
|
this.setState({ showPillAvatar });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private transform = (documentPosition: DocumentPosition) => {
|
||||||
|
const shouldReplace = SettingsStore.getValue('MessageComposerInput.autoReplaceEmoji');
|
||||||
|
if (shouldReplace) this.replaceEmoticon(documentPosition, REGEX_EMOTICON_WHITESPACE);
|
||||||
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
document.removeEventListener("selectionchange", this.onSelectionChange);
|
document.removeEventListener("selectionchange", this.onSelectionChange);
|
||||||
this.editorRef.current.removeEventListener("input", this.onInput, true);
|
this.editorRef.current.removeEventListener("input", this.onInput, true);
|
||||||
|
|
|
@ -28,7 +28,7 @@ import {
|
||||||
stripPrefix,
|
stripPrefix,
|
||||||
} from '../../../editor/serialize';
|
} from '../../../editor/serialize';
|
||||||
import {CommandPartCreator} from '../../../editor/parts';
|
import {CommandPartCreator} from '../../../editor/parts';
|
||||||
import BasicMessageComposer from "./BasicMessageComposer";
|
import BasicMessageComposer, {REGEX_EMOTICON} from "./BasicMessageComposer";
|
||||||
import ReplyThread from "../elements/ReplyThread";
|
import ReplyThread from "../elements/ReplyThread";
|
||||||
import {parseEvent} from '../../../editor/deserialize';
|
import {parseEvent} from '../../../editor/deserialize';
|
||||||
import {findEditableEvent} from '../../../utils/EventUtils';
|
import {findEditableEvent} from '../../../utils/EventUtils';
|
||||||
|
@ -334,6 +334,11 @@ export default class SendMessageComposer extends React.Component {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Replace emoticon at the end of the message
|
||||||
|
const caret = this._editorRef.getCaret();
|
||||||
|
const position = model.positionForOffset(caret.offset, caret.atNodeEnd);
|
||||||
|
this._editorRef.replaceEmoticon(position, REGEX_EMOTICON);
|
||||||
|
|
||||||
const replyToEvent = this.props.replyToEvent;
|
const replyToEvent = this.props.replyToEvent;
|
||||||
let shouldSend = true;
|
let shouldSend = true;
|
||||||
let content;
|
let content;
|
||||||
|
|
Loading…
Reference in a new issue