lexical: render native emojis as Twemoji

environments/review-emoji-node-jkqetp/deployments/4054
Alex Gleason 1 year ago
parent 2a9cb08d08
commit 4b5602a086
No known key found for this signature in database
GPG Key ID: 7211D1F99744FBB7

@ -1,7 +1,8 @@
import { $applyNodeReplacement, DecoratorNode } from 'lexical';
import React from 'react';
import { Emoji } from 'soapbox/components/ui';
import { Emoji as Component } from 'soapbox/components/ui';
import { isNativeEmoji, type Emoji } from 'soapbox/features/emoji';
import type {
DOMExportOutput,
@ -13,29 +14,26 @@ import type {
} from 'lexical';
type SerializedEmojiNode = Spread<{
name: string
src: string
data: Emoji
type: 'emoji'
version: 1
}, SerializedLexicalNode>;
class EmojiNode extends DecoratorNode<JSX.Element> {
__name: string;
__src: string;
__emoji: Emoji;
static getType(): 'emoji' {
return 'emoji';
}
static clone(node: EmojiNode): EmojiNode {
return new EmojiNode(node.__name, node.__src, node.__key);
return new EmojiNode(node.__emoji, node.__key);
}
constructor(name: string, src: string, key?: NodeKey) {
constructor(emoji: Emoji, key?: NodeKey) {
super(key);
this.__name = name;
this.__src = src;
this.__emoji = emoji;
}
createDOM(config: EditorConfig): HTMLElement {
@ -60,16 +58,13 @@ class EmojiNode extends DecoratorNode<JSX.Element> {
return { element };
}
static importJSON(serializedNode: SerializedEmojiNode): EmojiNode {
const { name, src } = serializedNode;
const node = $createEmojiNode(name, src);
return node;
static importJSON({ data }: SerializedEmojiNode): EmojiNode {
return $createEmojiNode(data);
}
exportJSON(): SerializedEmojiNode {
return {
name: this.__name,
src: this.__src,
data: this.__emoji,
type: 'emoji',
version: 1,
};
@ -88,15 +83,19 @@ class EmojiNode extends DecoratorNode<JSX.Element> {
}
decorate(): JSX.Element {
return (
<Emoji src={this.__src} alt={this.__name} className='emojione h-4 w-4' />
);
const emoji = this.__emoji;
if (isNativeEmoji(emoji)) {
return <Component emoji={emoji.native} alt={emoji.colons} className='emojione h-4 w-4' />;
} else {
return <Component src={emoji.imageUrl} alt={emoji.colons} className='emojione h-4 w-4' />;
}
}
}
function $createEmojiNode (name = '', src: string): EmojiNode {
const node = new EmojiNode(name, src);
function $createEmojiNode(emoji: Emoji): EmojiNode {
const node = new EmojiNode(emoji);
return $applyNodeReplacement(node);
}

@ -33,9 +33,8 @@ import React, {
import ReactDOM from 'react-dom';
import { clearComposeSuggestions, fetchComposeSuggestions } from 'soapbox/actions/compose';
import { useEmoji } from 'soapbox/actions/emojis';
import { useEmoji as chooseEmoji } from 'soapbox/actions/emojis';
import AutosuggestEmoji from 'soapbox/components/autosuggest-emoji';
import { isNativeEmoji } from 'soapbox/features/emoji';
import { useAppDispatch, useCompose } from 'soapbox/hooks';
import { selectAccount } from 'soapbox/selectors';
import { textAtCursorMatchesToken } from 'soapbox/utils/suggestions';
@ -322,13 +321,8 @@ const AutosuggestPlugin = ({
if (typeof suggestion === 'object') {
if (!suggestion.id) return;
dispatch(useEmoji(suggestion)); // eslint-disable-line react-hooks/rules-of-hooks
if (isNativeEmoji(suggestion)) {
node.spliceText(offset, matchingString.length, `${suggestion.native} `, true);
} else {
replaceMatch($createEmojiNode(suggestion.colons, suggestion.imageUrl));
}
dispatch(chooseEmoji(suggestion));
replaceMatch($createEmojiNode(suggestion));
} else if (suggestion[0] === '#') {
node.setTextContent(`${suggestion} `);
node.select();

Loading…
Cancel
Save