From 2a9cb08d08f7e60d7ed67a8a83c9b1bd31f02bfb Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Mon, 25 Sep 2023 15:46:29 -0500 Subject: [PATCH] lexical: restore EmojiNode, fix Android backspace! --- src/features/compose/editor/index.tsx | 1 + .../compose/editor/nodes/emoji-node.tsx | 5 ++++- .../editor/plugins/autosuggest-plugin.tsx | 19 +++++++++++++------ 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/features/compose/editor/index.tsx b/src/features/compose/editor/index.tsx index c5bcfb48e..d35762e6d 100644 --- a/src/features/compose/editor/index.tsx +++ b/src/features/compose/editor/index.tsx @@ -49,6 +49,7 @@ interface IComposeEditor { } const theme: InitialConfigType['theme'] = { + emoji: 'select-none', hashtag: 'hover:underline text-primary-600 dark:text-accent-blue hover:text-primary-800 dark:hover:text-accent-blue', mention: 'hover:underline text-primary-600 dark:text-accent-blue hover:text-primary-800 dark:hover:text-accent-blue', link: 'hover:underline text-primary-600 dark:text-accent-blue hover:text-primary-800 dark:hover:text-accent-blue', diff --git a/src/features/compose/editor/nodes/emoji-node.tsx b/src/features/compose/editor/nodes/emoji-node.tsx index 7f7d71767..9e2971206 100644 --- a/src/features/compose/editor/nodes/emoji-node.tsx +++ b/src/features/compose/editor/nodes/emoji-node.tsx @@ -95,7 +95,10 @@ class EmojiNode extends DecoratorNode { } -const $createEmojiNode = (name = '', src: string): EmojiNode => $applyNodeReplacement(new EmojiNode(name, src)); +function $createEmojiNode (name = '', src: string): EmojiNode { + const node = new EmojiNode(name, src); + return $applyNodeReplacement(node); +} const $isEmojiNode = ( node: LexicalNode | null | undefined, diff --git a/src/features/compose/editor/plugins/autosuggest-plugin.tsx b/src/features/compose/editor/plugins/autosuggest-plugin.tsx index f13fcaf55..222c1e979 100644 --- a/src/features/compose/editor/plugins/autosuggest-plugin.tsx +++ b/src/features/compose/editor/plugins/autosuggest-plugin.tsx @@ -18,6 +18,7 @@ import { KEY_ESCAPE_COMMAND, KEY_TAB_COMMAND, LexicalEditor, + LexicalNode, RangeSelection, TextNode, } from 'lexical'; @@ -40,6 +41,7 @@ import { selectAccount } from 'soapbox/selectors'; import { textAtCursorMatchesToken } from 'soapbox/utils/suggestions'; import AutosuggestAccount from '../../components/autosuggest-account'; +import { $createEmojiNode } from '../nodes/emoji-node'; import { $createMentionNode } from '../nodes/mention-node'; import type { AutoSuggestion } from 'soapbox/components/autosuggest-input'; @@ -309,6 +311,15 @@ const AutosuggestPlugin = ({ /** Offset for the beginning of the matched text, including the token. */ const offset = leadOffset - 1; + /** Replace the matched text with the given node. */ + function replaceMatch(replaceWith: LexicalNode) { + const result = (node as TextNode).splitText(offset, offset + matchingString.length); + const textNode = result[1] ?? result[0]; + const replacedNode = textNode.replace(replaceWith); + replacedNode.insertAfter(new TextNode(' ')); + replacedNode.selectNext(); + } + if (typeof suggestion === 'object') { if (!suggestion.id) return; dispatch(useEmoji(suggestion)); // eslint-disable-line react-hooks/rules-of-hooks @@ -316,18 +327,14 @@ const AutosuggestPlugin = ({ if (isNativeEmoji(suggestion)) { node.spliceText(offset, matchingString.length, `${suggestion.native} `, true); } else { - node.spliceText(offset, matchingString.length, `${suggestion.colons} `, true); + replaceMatch($createEmojiNode(suggestion.colons, suggestion.imageUrl)); } } else if (suggestion[0] === '#') { node.setTextContent(`${suggestion} `); node.select(); } else { const acct = selectAccount(getState(), suggestion)!.acct; - const result = (node as TextNode).splitText(offset, offset + matchingString.length); - const textNode = result[1] ?? result[0]; - const mentionNode = textNode.replace($createMentionNode(`@${acct}`)); - mentionNode.insertAfter(new TextNode(' ')); - mentionNode.selectNext(); + replaceMatch($createMentionNode(`@${acct}`)); } dispatch(clearComposeSuggestions(composeId));