lexical: restore EmojiNode, fix Android backspace!
This commit is contained in:
parent
29974c33e7
commit
2a9cb08d08
|
@ -49,6 +49,7 @@ interface IComposeEditor {
|
||||||
}
|
}
|
||||||
|
|
||||||
const theme: InitialConfigType['theme'] = {
|
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',
|
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',
|
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',
|
link: 'hover:underline text-primary-600 dark:text-accent-blue hover:text-primary-800 dark:hover:text-accent-blue',
|
||||||
|
|
|
@ -95,7 +95,10 @@ class EmojiNode extends DecoratorNode<JSX.Element> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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 = (
|
const $isEmojiNode = (
|
||||||
node: LexicalNode | null | undefined,
|
node: LexicalNode | null | undefined,
|
||||||
|
|
|
@ -18,6 +18,7 @@ import {
|
||||||
KEY_ESCAPE_COMMAND,
|
KEY_ESCAPE_COMMAND,
|
||||||
KEY_TAB_COMMAND,
|
KEY_TAB_COMMAND,
|
||||||
LexicalEditor,
|
LexicalEditor,
|
||||||
|
LexicalNode,
|
||||||
RangeSelection,
|
RangeSelection,
|
||||||
TextNode,
|
TextNode,
|
||||||
} from 'lexical';
|
} from 'lexical';
|
||||||
|
@ -40,6 +41,7 @@ import { selectAccount } from 'soapbox/selectors';
|
||||||
import { textAtCursorMatchesToken } from 'soapbox/utils/suggestions';
|
import { textAtCursorMatchesToken } from 'soapbox/utils/suggestions';
|
||||||
|
|
||||||
import AutosuggestAccount from '../../components/autosuggest-account';
|
import AutosuggestAccount from '../../components/autosuggest-account';
|
||||||
|
import { $createEmojiNode } from '../nodes/emoji-node';
|
||||||
import { $createMentionNode } from '../nodes/mention-node';
|
import { $createMentionNode } from '../nodes/mention-node';
|
||||||
|
|
||||||
import type { AutoSuggestion } from 'soapbox/components/autosuggest-input';
|
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. */
|
/** Offset for the beginning of the matched text, including the token. */
|
||||||
const offset = leadOffset - 1;
|
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 (typeof suggestion === 'object') {
|
||||||
if (!suggestion.id) return;
|
if (!suggestion.id) return;
|
||||||
dispatch(useEmoji(suggestion)); // eslint-disable-line react-hooks/rules-of-hooks
|
dispatch(useEmoji(suggestion)); // eslint-disable-line react-hooks/rules-of-hooks
|
||||||
|
@ -316,18 +327,14 @@ const AutosuggestPlugin = ({
|
||||||
if (isNativeEmoji(suggestion)) {
|
if (isNativeEmoji(suggestion)) {
|
||||||
node.spliceText(offset, matchingString.length, `${suggestion.native} `, true);
|
node.spliceText(offset, matchingString.length, `${suggestion.native} `, true);
|
||||||
} else {
|
} else {
|
||||||
node.spliceText(offset, matchingString.length, `${suggestion.colons} `, true);
|
replaceMatch($createEmojiNode(suggestion.colons, suggestion.imageUrl));
|
||||||
}
|
}
|
||||||
} else if (suggestion[0] === '#') {
|
} else if (suggestion[0] === '#') {
|
||||||
node.setTextContent(`${suggestion} `);
|
node.setTextContent(`${suggestion} `);
|
||||||
node.select();
|
node.select();
|
||||||
} else {
|
} else {
|
||||||
const acct = selectAccount(getState(), suggestion)!.acct;
|
const acct = selectAccount(getState(), suggestion)!.acct;
|
||||||
const result = (node as TextNode).splitText(offset, offset + matchingString.length);
|
replaceMatch($createMentionNode(`@${acct}`));
|
||||||
const textNode = result[1] ?? result[0];
|
|
||||||
const mentionNode = textNode.replace($createMentionNode(`@${acct}`));
|
|
||||||
mentionNode.insertAfter(new TextNode(' '));
|
|
||||||
mentionNode.selectNext();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch(clearComposeSuggestions(composeId));
|
dispatch(clearComposeSuggestions(composeId));
|
||||||
|
|
Loading…
Reference in New Issue