feat(input): added ascii to emoji conversion
This commit is contained in:
parent
68dfc46185
commit
e4ab71eb78
2 changed files with 99 additions and 0 deletions
|
@ -61,12 +61,14 @@ import {
|
|||
matchStrikethrough,
|
||||
} from '../quill/formatting/matchers';
|
||||
import { missingCaseError } from '../util/missingCaseError';
|
||||
import { AutoSubstituteAsciiEmojis } from '../quill/auto-substitute-ascii-emojis';
|
||||
|
||||
Quill.register('formats/emoji', EmojiBlot);
|
||||
Quill.register('formats/mention', MentionBlot);
|
||||
Quill.register('formats/block', DirectionalBlot);
|
||||
Quill.register('formats/monospace', MonospaceBlot);
|
||||
Quill.register('formats/spoiler', SpoilerBlot);
|
||||
Quill.register('modules/autoSubstituteAsciiEmojis', AutoSubstituteAsciiEmojis);
|
||||
Quill.register('modules/emojiCompletion', EmojiCompletion);
|
||||
Quill.register('modules/mentionCompletion', MentionCompletion);
|
||||
Quill.register('modules/formattingMenu', FormattingMenu);
|
||||
|
@ -767,6 +769,7 @@ export function CompositionInput(props: Props): React.ReactElement {
|
|||
callbacksRef.current.onPickEmoji(emoji),
|
||||
skinTone,
|
||||
},
|
||||
autoSubstituteAsciiEmojis: true,
|
||||
formattingMenu: {
|
||||
i18n,
|
||||
isMenuEnabled: isFormattingEnabled,
|
||||
|
|
96
ts/quill/auto-substitute-ascii-emojis/index.tsx
Normal file
96
ts/quill/auto-substitute-ascii-emojis/index.tsx
Normal file
|
@ -0,0 +1,96 @@
|
|||
// Copyright 2020 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import type Quill from 'quill';
|
||||
import Delta from 'quill-delta';
|
||||
import _ from 'lodash';
|
||||
import type { EmojiData } from '../../components/emoji/lib';
|
||||
import {
|
||||
convertShortName,
|
||||
convertShortNameToData,
|
||||
} from '../../components/emoji/lib';
|
||||
|
||||
type AutoSubstituteAsciiEmojisOptions = {
|
||||
skinTone: number;
|
||||
};
|
||||
|
||||
const emojiMap: Record<string, string> = {
|
||||
':)': 'slightly_smiling_face',
|
||||
':-)': 'slightly_smiling_face',
|
||||
':(': 'slightly_frowning_face',
|
||||
':-(': 'slightly_frowning_face',
|
||||
':D': 'smiley',
|
||||
':-D': 'smiley',
|
||||
':*': 'kissing',
|
||||
':-*': 'kissing',
|
||||
':P': 'stuck_out_tongue',
|
||||
':-P': 'stuck_out_tongue',
|
||||
';P': 'stuck_out_tongue_winking_eye',
|
||||
';-P': 'stuck_out_tongue_winking_eye',
|
||||
'D:': 'anguished',
|
||||
"D-':": 'anguished',
|
||||
':O': 'open_mouth',
|
||||
':-O': 'open_mouth',
|
||||
":'(": 'cry',
|
||||
":'-(": 'cry',
|
||||
':/': 'confused',
|
||||
':-/': 'confused',
|
||||
';)': 'wink',
|
||||
';-)': 'wink',
|
||||
'(Y)': '+1',
|
||||
'(N)': '-1',
|
||||
};
|
||||
|
||||
export class AutoSubstituteAsciiEmojis {
|
||||
options: AutoSubstituteAsciiEmojisOptions;
|
||||
|
||||
quill: Quill;
|
||||
|
||||
constructor(quill: Quill, options: AutoSubstituteAsciiEmojisOptions) {
|
||||
this.options = options;
|
||||
this.quill = quill;
|
||||
|
||||
this.quill.on(
|
||||
'text-change',
|
||||
_.debounce(() => this.onTextChange(), 100)
|
||||
);
|
||||
}
|
||||
|
||||
onTextChange(): void {
|
||||
const range = this.quill.getSelection();
|
||||
|
||||
if (!range) {
|
||||
return;
|
||||
}
|
||||
|
||||
const [blot, index] = this.quill.getLeaf(range.index);
|
||||
|
||||
if (blot !== undefined && blot.text !== undefined) {
|
||||
const blotText: string = blot.text;
|
||||
Object.entries(emojiMap).some(([textEmoji, emojiName]) => {
|
||||
if (blotText.substring(0, index).endsWith(textEmoji)) {
|
||||
const emojiData = convertShortNameToData(
|
||||
emojiName,
|
||||
this.options.skinTone
|
||||
);
|
||||
if (emojiData) {
|
||||
this.insertEmoji(
|
||||
emojiData,
|
||||
range.index - textEmoji.length,
|
||||
textEmoji.length
|
||||
);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
insertEmoji(emojiData: EmojiData, index: number, range: number): void {
|
||||
const emoji = convertShortName(emojiData.short_name, this.options.skinTone);
|
||||
const delta = new Delta().retain(index).delete(range).insert({ emoji });
|
||||
this.quill.updateContents(delta, 'user');
|
||||
this.quill.setSelection(index + 1, 0);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue