Revert custom caret navigation logic
This commit is contained in:
parent
fa70fa2ecf
commit
7064691696
2 changed files with 36 additions and 353 deletions
|
@ -23,9 +23,8 @@ import { Emoji } from './emoji/Emoji';
|
||||||
import { EmojiPickDataType } from './emoji/EmojiPicker';
|
import { EmojiPickDataType } from './emoji/EmojiPicker';
|
||||||
import {
|
import {
|
||||||
convertShortName,
|
convertShortName,
|
||||||
DataFromEmojiText,
|
|
||||||
EmojiData,
|
EmojiData,
|
||||||
emojiToData,
|
replaceColons,
|
||||||
search,
|
search,
|
||||||
} from './emoji/lib';
|
} from './emoji/lib';
|
||||||
import { LocalizerType } from '../types/Util';
|
import { LocalizerType } from '../types/Util';
|
||||||
|
@ -152,78 +151,6 @@ function getWordAtIndex(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace bare (non-entitied) emojis with draft entities
|
|
||||||
function replaceBareEmojis(state: EditorState, focus: boolean): EditorState {
|
|
||||||
// Track emoji positions
|
|
||||||
const selections: Array<[SelectionState, DataFromEmojiText]> = [];
|
|
||||||
|
|
||||||
const content = state.getCurrentContent();
|
|
||||||
const initialSelection = state.getSelection();
|
|
||||||
|
|
||||||
content.getBlockMap().forEach(block => {
|
|
||||||
if (!block) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const pat = emojiRegex();
|
|
||||||
const text = block.getText();
|
|
||||||
let match;
|
|
||||||
// tslint:disable-next-line
|
|
||||||
while ((match = pat.exec(text)) !== null) {
|
|
||||||
const start = match.index;
|
|
||||||
const end = start + match[0].length;
|
|
||||||
const blockKey = block.getKey();
|
|
||||||
const blockSelection = SelectionState.createEmpty(blockKey).merge({
|
|
||||||
anchorOffset: start,
|
|
||||||
focusOffset: end,
|
|
||||||
}) as SelectionState;
|
|
||||||
const emojiData = emojiToData(match[0]);
|
|
||||||
// If there is no entity at this location and emoji data exists for the
|
|
||||||
// emoji at this location, track it for replacement
|
|
||||||
if (!block.getEntityAt(start) && emojiData) {
|
|
||||||
selections.push([blockSelection, emojiData]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const newContent = selections.reduce(
|
|
||||||
(accContent, [sel, { shortName, tone }]) => {
|
|
||||||
const emojiContent = convertShortName(shortName);
|
|
||||||
const emojiEntityKey = accContent
|
|
||||||
.createEntity('emoji', 'IMMUTABLE', {
|
|
||||||
shortName: shortName,
|
|
||||||
skinTone: tone,
|
|
||||||
})
|
|
||||||
.getLastCreatedEntityKey();
|
|
||||||
|
|
||||||
return Modifier.replaceText(
|
|
||||||
accContent,
|
|
||||||
sel,
|
|
||||||
emojiContent,
|
|
||||||
undefined,
|
|
||||||
emojiEntityKey
|
|
||||||
);
|
|
||||||
},
|
|
||||||
content
|
|
||||||
);
|
|
||||||
|
|
||||||
const pushState = EditorState.push(
|
|
||||||
state,
|
|
||||||
newContent,
|
|
||||||
'replace-emoji' as EditorChangeType
|
|
||||||
);
|
|
||||||
|
|
||||||
if (focus) {
|
|
||||||
const newSelection = initialSelection.merge({
|
|
||||||
anchorOffset: initialSelection.getAnchorOffset(),
|
|
||||||
focusOffset: initialSelection.getFocusOffset(),
|
|
||||||
}) as SelectionState;
|
|
||||||
|
|
||||||
return EditorState.forceSelection(pushState, newSelection);
|
|
||||||
}
|
|
||||||
|
|
||||||
return pushState;
|
|
||||||
}
|
|
||||||
|
|
||||||
const compositeDecorator = new CompositeDecorator([
|
const compositeDecorator = new CompositeDecorator([
|
||||||
{
|
{
|
||||||
strategy: (block, cb) => {
|
strategy: (block, cb) => {
|
||||||
|
@ -280,15 +207,18 @@ const getInitialEditorState = (startingText?: string) => {
|
||||||
return EditorState.createEmpty(compositeDecorator);
|
return EditorState.createEmpty(compositeDecorator);
|
||||||
}
|
}
|
||||||
|
|
||||||
const state = replaceBareEmojis(
|
const end = startingText.length;
|
||||||
EditorState.createWithContent(
|
const state = EditorState.createWithContent(
|
||||||
ContentState.createFromText(startingText),
|
ContentState.createFromText(startingText),
|
||||||
compositeDecorator
|
compositeDecorator
|
||||||
),
|
|
||||||
false
|
|
||||||
);
|
);
|
||||||
|
const selection = state.getSelection();
|
||||||
|
const selectionAtEnd = selection.merge({
|
||||||
|
anchorOffset: end,
|
||||||
|
focusOffset: end,
|
||||||
|
}) as SelectionState;
|
||||||
|
|
||||||
return EditorState.moveFocusToEnd(state);
|
return EditorState.forceSelection(state, selectionAtEnd);
|
||||||
};
|
};
|
||||||
|
|
||||||
// tslint:disable-next-line max-func-body-length
|
// tslint:disable-next-line max-func-body-length
|
||||||
|
@ -321,7 +251,6 @@ export const CompositionInput = ({
|
||||||
const focusRef = React.useRef(false);
|
const focusRef = React.useRef(false);
|
||||||
const editorStateRef = React.useRef<EditorState>(editorRenderState);
|
const editorStateRef = React.useRef<EditorState>(editorRenderState);
|
||||||
const rootElRef = React.useRef<HTMLDivElement>();
|
const rootElRef = React.useRef<HTMLDivElement>();
|
||||||
const latestKeyRef = React.useRef<string>();
|
|
||||||
|
|
||||||
// This function sets editorState and also keeps a reference to the newly set
|
// This function sets editorState and also keeps a reference to the newly set
|
||||||
// state so we can reference the state in effects and callbacks without
|
// state so we can reference the state in effects and callbacks without
|
||||||
|
@ -336,10 +265,7 @@ export const CompositionInput = ({
|
||||||
|
|
||||||
const updateExternalStateListeners = React.useCallback(
|
const updateExternalStateListeners = React.useCallback(
|
||||||
(newState: EditorState) => {
|
(newState: EditorState) => {
|
||||||
const plainText = newState
|
const plainText = newState.getCurrentContent().getPlainText();
|
||||||
.getCurrentContent()
|
|
||||||
.getPlainText()
|
|
||||||
.trim();
|
|
||||||
const cursorBlockKey = newState.getSelection().getStartKey();
|
const cursorBlockKey = newState.getSelection().getStartKey();
|
||||||
const cursorBlockIndex = editorStateRef.current
|
const cursorBlockIndex = editorStateRef.current
|
||||||
.getCurrentContent()
|
.getCurrentContent()
|
||||||
|
@ -389,20 +315,6 @@ export const CompositionInput = ({
|
||||||
|
|
||||||
const handleEditorStateChange = React.useCallback(
|
const handleEditorStateChange = React.useCallback(
|
||||||
(newState: EditorState) => {
|
(newState: EditorState) => {
|
||||||
// If this is an undo, we don't want to trigger any other custom logic
|
|
||||||
if (newState.getLastChangeType() === 'undo') {
|
|
||||||
// Does this undo result in the same state as before?
|
|
||||||
const pointlessUndo =
|
|
||||||
newState.getCurrentContent().getPlainText() ===
|
|
||||||
editorStateRef.current.getCurrentContent().getPlainText();
|
|
||||||
// If so, we need to apply another undo
|
|
||||||
const pushState = pointlessUndo ? EditorState.undo(newState) : newState;
|
|
||||||
// Update state
|
|
||||||
setAndTrackEditorState(pushState);
|
|
||||||
resetEmojiResults();
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Does the current position have any emojiable text?
|
// Does the current position have any emojiable text?
|
||||||
const selection = newState.getSelection();
|
const selection = newState.getSelection();
|
||||||
const caretLocation = selection.getStartOffset();
|
const caretLocation = selection.getStartOffset();
|
||||||
|
@ -414,7 +326,7 @@ export const CompositionInput = ({
|
||||||
|
|
||||||
// Update the state to indicate emojiable text at the current position.
|
// Update the state to indicate emojiable text at the current position.
|
||||||
const newSearchText = match ? match.trim().substr(1) : '';
|
const newSearchText = match ? match.trim().substr(1) : '';
|
||||||
if (newSearchText.endsWith(':') && latestKeyRef.current === ':') {
|
if (newSearchText.endsWith(':')) {
|
||||||
const bareText = trimEnd(newSearchText, ':');
|
const bareText = trimEnd(newSearchText, ':');
|
||||||
const emoji = head(search(bareText));
|
const emoji = head(search(bareText));
|
||||||
if (emoji && bareText === emoji.short_name) {
|
if (emoji && bareText === emoji.short_name) {
|
||||||
|
@ -433,16 +345,12 @@ export const CompositionInput = ({
|
||||||
resetEmojiResults();
|
resetEmojiResults();
|
||||||
}
|
}
|
||||||
|
|
||||||
const modifiedState = replaceBareEmojis(newState, focusRef.current);
|
|
||||||
|
|
||||||
// Finally, update the editor state
|
// Finally, update the editor state
|
||||||
setAndTrackEditorState(modifiedState);
|
setAndTrackEditorState(newState);
|
||||||
updateExternalStateListeners(modifiedState);
|
updateExternalStateListeners(newState);
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
editorStateRef,
|
|
||||||
focusRef,
|
focusRef,
|
||||||
latestKeyRef,
|
|
||||||
resetEmojiResults,
|
resetEmojiResults,
|
||||||
setAndTrackEditorState,
|
setAndTrackEditorState,
|
||||||
setSearchText,
|
setSearchText,
|
||||||
|
@ -508,8 +416,8 @@ export const CompositionInput = ({
|
||||||
() => {
|
() => {
|
||||||
const { current: state } = editorStateRef;
|
const { current: state } = editorStateRef;
|
||||||
const text = state.getCurrentContent().getPlainText();
|
const text = state.getCurrentContent().getPlainText();
|
||||||
const trimmedText = text.trim();
|
const emojidText = replaceColons(text);
|
||||||
onSubmit(trimmedText);
|
onSubmit(emojidText);
|
||||||
},
|
},
|
||||||
[editorStateRef, onSubmit]
|
[editorStateRef, onSubmit]
|
||||||
);
|
);
|
||||||
|
@ -561,212 +469,17 @@ export const CompositionInput = ({
|
||||||
[emojiResultsIndex, emojiResults]
|
[emojiResultsIndex, emojiResults]
|
||||||
);
|
);
|
||||||
|
|
||||||
const modKeySelection = React.useCallback(
|
|
||||||
// tslint:disable-next-line cyclomatic-complexity max-func-body-length
|
|
||||||
(e: React.KeyboardEvent) => {
|
|
||||||
e.preventDefault();
|
|
||||||
const { current: state } = editorStateRef;
|
|
||||||
const selection = state.getSelection();
|
|
||||||
|
|
||||||
const newSelectionDesc: Partial<{
|
|
||||||
anchorKey: string;
|
|
||||||
anchorOffset: number;
|
|
||||||
focusKey: string;
|
|
||||||
focusOffset: number;
|
|
||||||
}> = {};
|
|
||||||
|
|
||||||
if (
|
|
||||||
(e.shiftKey && (e.metaKey && e.key === 'ArrowUp')) ||
|
|
||||||
e.key === 'Home'
|
|
||||||
) {
|
|
||||||
const block = state.getCurrentContent().getFirstBlock();
|
|
||||||
newSelectionDesc.anchorKey = block.getKey();
|
|
||||||
newSelectionDesc.anchorOffset = 0;
|
|
||||||
} else if (
|
|
||||||
(e.shiftKey && (e.metaKey && e.key === 'ArrowDown')) ||
|
|
||||||
e.key === 'End'
|
|
||||||
) {
|
|
||||||
const block = state.getCurrentContent().getLastBlock();
|
|
||||||
newSelectionDesc.focusKey = block.getKey();
|
|
||||||
newSelectionDesc.focusOffset = block.getText().length;
|
|
||||||
} else if (
|
|
||||||
e.shiftKey &&
|
|
||||||
((e.metaKey && e.key === 'ArrowLeft') || e.key === 'Home')
|
|
||||||
) {
|
|
||||||
newSelectionDesc.anchorOffset = 0;
|
|
||||||
} else if (
|
|
||||||
e.shiftKey &&
|
|
||||||
((e.metaKey && e.key === 'ArrowRight') || e.key === 'End')
|
|
||||||
) {
|
|
||||||
newSelectionDesc.focusOffset = state
|
|
||||||
.getCurrentContent()
|
|
||||||
.getBlockForKey(selection.getFocusKey())
|
|
||||||
.getText().length;
|
|
||||||
} else if (e.shiftKey && e.key === 'ArrowLeft') {
|
|
||||||
newSelectionDesc.anchorOffset = selection.getAnchorOffset() - 1;
|
|
||||||
if (newSelectionDesc.anchorOffset < 0) {
|
|
||||||
newSelectionDesc.anchorOffset = 0;
|
|
||||||
const block = state
|
|
||||||
.getCurrentContent()
|
|
||||||
.getBlockBefore(selection.getAnchorKey());
|
|
||||||
if (block) {
|
|
||||||
newSelectionDesc.anchorKey = block.getKey();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (e.shiftKey && e.key === 'ArrowRight') {
|
|
||||||
newSelectionDesc.focusOffset = selection.getFocusOffset() + 1;
|
|
||||||
const { length } = state
|
|
||||||
.getCurrentContent()
|
|
||||||
.getBlockForKey(selection.getFocusKey())
|
|
||||||
.getText();
|
|
||||||
if (newSelectionDesc.focusOffset > length) {
|
|
||||||
newSelectionDesc.focusOffset = length;
|
|
||||||
const block = state
|
|
||||||
.getCurrentContent()
|
|
||||||
.getBlockAfter(selection.getAnchorKey());
|
|
||||||
if (block) {
|
|
||||||
newSelectionDesc.anchorKey = block.getKey();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (e.shiftKey && e.key === 'ArrowUp') {
|
|
||||||
if (selection.getIsBackward()) {
|
|
||||||
const block = state
|
|
||||||
.getCurrentContent()
|
|
||||||
.getBlockBefore(selection.getFocusKey());
|
|
||||||
newSelectionDesc.focusOffset = 0;
|
|
||||||
if (block) {
|
|
||||||
newSelectionDesc.focusKey = block.getKey();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const block = state
|
|
||||||
.getCurrentContent()
|
|
||||||
.getBlockBefore(selection.getAnchorKey());
|
|
||||||
newSelectionDesc.anchorOffset = 0;
|
|
||||||
if (block) {
|
|
||||||
newSelectionDesc.anchorKey = block.getKey();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (e.shiftKey && e.key === 'ArrowDown') {
|
|
||||||
if (selection.getIsBackward()) {
|
|
||||||
const block = state
|
|
||||||
.getCurrentContent()
|
|
||||||
.getBlockAfter(selection.getAnchorKey());
|
|
||||||
if (block) {
|
|
||||||
newSelectionDesc.anchorKey = block.getKey();
|
|
||||||
newSelectionDesc.anchorOffset = block.getText().length;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const block = state
|
|
||||||
.getCurrentContent()
|
|
||||||
.getBlockAfter(selection.getFocusKey());
|
|
||||||
if (block) {
|
|
||||||
newSelectionDesc.focusKey = block.getKey();
|
|
||||||
newSelectionDesc.focusOffset = block.getText().length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if ((e.metaKey && e.key === 'ArrowLeft') || e.key === 'Home') {
|
|
||||||
newSelectionDesc.anchorOffset = 0;
|
|
||||||
newSelectionDesc.focusOffset = 0;
|
|
||||||
} else if ((e.metaKey && e.key === 'ArrowRight') || e.key === 'End') {
|
|
||||||
const { length } = state
|
|
||||||
.getCurrentContent()
|
|
||||||
.getBlockForKey(selection.getAnchorKey())
|
|
||||||
.getText();
|
|
||||||
newSelectionDesc.anchorOffset = length;
|
|
||||||
newSelectionDesc.focusOffset = length;
|
|
||||||
} else if (e.key === 'ArrowLeft') {
|
|
||||||
newSelectionDesc.anchorOffset = selection.getAnchorOffset() - 1;
|
|
||||||
if (newSelectionDesc.anchorOffset < 0) {
|
|
||||||
newSelectionDesc.anchorOffset = 0;
|
|
||||||
const block = state
|
|
||||||
.getCurrentContent()
|
|
||||||
.getBlockBefore(selection.getAnchorKey());
|
|
||||||
if (block) {
|
|
||||||
newSelectionDesc.anchorKey = block.getKey();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (e.key === 'ArrowRight') {
|
|
||||||
newSelectionDesc.focusOffset = selection.getFocusOffset() + 1;
|
|
||||||
const { length } = state
|
|
||||||
.getCurrentContent()
|
|
||||||
.getBlockForKey(selection.getFocusKey())
|
|
||||||
.getText();
|
|
||||||
if (newSelectionDesc.focusOffset > length) {
|
|
||||||
newSelectionDesc.anchorOffset = length;
|
|
||||||
const block = state
|
|
||||||
.getCurrentContent()
|
|
||||||
.getBlockAfter(selection.getFocusKey());
|
|
||||||
if (block) {
|
|
||||||
newSelectionDesc.focusKey = block.getKey();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {
|
|
||||||
const content = state.getCurrentContent();
|
|
||||||
const anchorKey = selection.getAnchorKey();
|
|
||||||
const block =
|
|
||||||
e.key === 'ArrowUp'
|
|
||||||
? content.getBlockBefore(anchorKey)
|
|
||||||
: content.getBlockAfter(anchorKey);
|
|
||||||
if (block) {
|
|
||||||
const key = block.getKey();
|
|
||||||
const length = block.getText().length;
|
|
||||||
newSelectionDesc.anchorKey = key;
|
|
||||||
newSelectionDesc.focusKey = key;
|
|
||||||
const offset = selection.getAnchorOffset();
|
|
||||||
newSelectionDesc.anchorOffset = Math.min(length, offset);
|
|
||||||
newSelectionDesc.focusOffset = Math.min(length, offset);
|
|
||||||
} else {
|
|
||||||
if (e.key === 'ArrowUp') {
|
|
||||||
const key = content.getFirstBlock().getKey();
|
|
||||||
newSelectionDesc.anchorKey = key;
|
|
||||||
newSelectionDesc.focusKey = key;
|
|
||||||
newSelectionDesc.anchorOffset = 0;
|
|
||||||
newSelectionDesc.focusOffset = 0;
|
|
||||||
} else {
|
|
||||||
const lastBlock = content.getLastBlock();
|
|
||||||
const key = lastBlock.getKey();
|
|
||||||
const { length } = lastBlock.getText();
|
|
||||||
newSelectionDesc.anchorKey = key;
|
|
||||||
newSelectionDesc.focusKey = key;
|
|
||||||
newSelectionDesc.anchorOffset = length;
|
|
||||||
newSelectionDesc.focusOffset = length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const newSelection = selection.merge(newSelectionDesc) as SelectionState;
|
|
||||||
setAndTrackEditorState(EditorState.forceSelection(state, newSelection));
|
|
||||||
},
|
|
||||||
[editorStateRef, setAndTrackEditorState]
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleEditorArrowKey = React.useCallback(
|
const handleEditorArrowKey = React.useCallback(
|
||||||
(e: React.KeyboardEvent) => {
|
(e: React.KeyboardEvent) => {
|
||||||
latestKeyRef.current = e.key;
|
|
||||||
|
|
||||||
if (e.key === 'ArrowUp') {
|
if (e.key === 'ArrowUp') {
|
||||||
modKeySelection(e);
|
|
||||||
if (!e.shiftKey) {
|
|
||||||
selectEmojiResult('prev', e);
|
selectEmojiResult('prev', e);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (e.key === 'ArrowDown') {
|
if (e.key === 'ArrowDown') {
|
||||||
modKeySelection(e);
|
|
||||||
if (!e.shiftKey) {
|
|
||||||
selectEmojiResult('next', e);
|
selectEmojiResult('next', e);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (e.key === 'ArrowLeft' && e.metaKey) {
|
|
||||||
modKeySelection(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.key === 'ArrowRight' && e.metaKey) {
|
|
||||||
modKeySelection(e);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
[latestKeyRef, selectEmojiResult, modKeySelection]
|
[selectEmojiResult]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleEscapeKey = React.useCallback(
|
const handleEscapeKey = React.useCallback(
|
||||||
|
@ -916,7 +629,6 @@ export const CompositionInput = ({
|
||||||
resetEmojiResults,
|
resetEmojiResults,
|
||||||
selectEmojiResult,
|
selectEmojiResult,
|
||||||
setAndTrackEditorState,
|
setAndTrackEditorState,
|
||||||
modKeySelection,
|
|
||||||
skinTone,
|
skinTone,
|
||||||
submit,
|
submit,
|
||||||
]
|
]
|
||||||
|
@ -935,10 +647,7 @@ export const CompositionInput = ({
|
||||||
);
|
);
|
||||||
|
|
||||||
const editorKeybindingFn = React.useCallback(
|
const editorKeybindingFn = React.useCallback(
|
||||||
// tslint:disable-next-line cyclomatic-complexity
|
|
||||||
(e: React.KeyboardEvent): CompositionInputEditorCommand | null => {
|
(e: React.KeyboardEvent): CompositionInputEditorCommand | null => {
|
||||||
latestKeyRef.current = e.key;
|
|
||||||
|
|
||||||
if (e.key === 'Enter' && emojiResults.length > 0) {
|
if (e.key === 'Enter' && emojiResults.length > 0) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
|
@ -955,30 +664,6 @@ export const CompositionInput = ({
|
||||||
return 'submit';
|
return 'submit';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e.shiftKey && e.key === 'End') {
|
|
||||||
modKeySelection(e);
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.key === 'End') {
|
|
||||||
modKeySelection(e);
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.shiftKey && e.key === 'Home') {
|
|
||||||
modKeySelection(e);
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.key === 'Home') {
|
|
||||||
modKeySelection(e);
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.key === 'n' && e.ctrlKey) {
|
if (e.key === 'n' && e.ctrlKey) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
|
@ -1005,7 +690,7 @@ export const CompositionInput = ({
|
||||||
|
|
||||||
return getDefaultKeyBinding(e);
|
return getDefaultKeyBinding(e);
|
||||||
},
|
},
|
||||||
[latestKeyRef, emojiResults, large, modKeySelection]
|
[emojiResults, large]
|
||||||
);
|
);
|
||||||
|
|
||||||
// Create popper root
|
// Create popper root
|
||||||
|
@ -1057,7 +742,6 @@ export const CompositionInput = ({
|
||||||
setAndTrackEditorState(
|
setAndTrackEditorState(
|
||||||
EditorState.forceSelection(oldState, oldState.getSelection())
|
EditorState.forceSelection(oldState, oldState.getSelection())
|
||||||
);
|
);
|
||||||
onFocus();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
rootEl.addEventListener('focusin', onFocusIn);
|
rootEl.addEventListener('focusin', onFocusIn);
|
||||||
|
@ -1069,7 +753,7 @@ export const CompositionInput = ({
|
||||||
|
|
||||||
return noop;
|
return noop;
|
||||||
},
|
},
|
||||||
[editorStateRef, onFocus, rootElRef, setAndTrackEditorState]
|
[editorStateRef, rootElRef, setAndTrackEditorState]
|
||||||
);
|
);
|
||||||
|
|
||||||
if (inputApi) {
|
if (inputApi) {
|
||||||
|
@ -1106,8 +790,6 @@ export const CompositionInput = ({
|
||||||
placeholder={i18n('sendMessage')}
|
placeholder={i18n('sendMessage')}
|
||||||
onUpArrow={handleEditorArrowKey}
|
onUpArrow={handleEditorArrowKey}
|
||||||
onDownArrow={handleEditorArrowKey}
|
onDownArrow={handleEditorArrowKey}
|
||||||
onLeftArrow={handleEditorArrowKey}
|
|
||||||
onRightArrow={handleEditorArrowKey}
|
|
||||||
onEscape={handleEscapeKey}
|
onEscape={handleEscapeKey}
|
||||||
onTab={onTab}
|
onTab={onTab}
|
||||||
handleKeyCommand={handleEditorCommand}
|
handleKeyCommand={handleEditorCommand}
|
||||||
|
|
|
@ -38,11 +38,6 @@ export type EmojiSkinVariation = {
|
||||||
has_img_messenger: boolean;
|
has_img_messenger: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type DataFromEmojiText = {
|
|
||||||
shortName: string;
|
|
||||||
tone?: SkinToneKey;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type EmojiData = {
|
export type EmojiData = {
|
||||||
name: string;
|
name: string;
|
||||||
unified: string;
|
unified: string;
|
||||||
|
@ -121,7 +116,6 @@ export const preloadImages = async () => {
|
||||||
|
|
||||||
const dataByShortName = keyBy(data, 'short_name');
|
const dataByShortName = keyBy(data, 'short_name');
|
||||||
const imageByEmoji: { [key: string]: string } = {};
|
const imageByEmoji: { [key: string]: string } = {};
|
||||||
const dataByEmoji: { [key: string]: DataFromEmojiText } = {};
|
|
||||||
|
|
||||||
export const dataByCategory = mapValues(
|
export const dataByCategory = mapValues(
|
||||||
groupBy(data, ({ category }) => {
|
groupBy(data, ({ category }) => {
|
||||||
|
@ -248,8 +242,20 @@ export function emojiToImage(emoji: string): string | undefined {
|
||||||
return imageByEmoji[emoji];
|
return imageByEmoji[emoji];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function emojiToData(emoji: string): DataFromEmojiText | undefined {
|
export function replaceColons(str: string) {
|
||||||
return dataByEmoji[emoji];
|
return str.replace(/:[a-z0-9-_+]+:(?::skin-tone-[1-5]:)?/gi, m => {
|
||||||
|
const [shortName = '', skinTone = '0'] = m
|
||||||
|
.replace('skin-tone-', '')
|
||||||
|
.toLowerCase()
|
||||||
|
.split(':')
|
||||||
|
.filter(Boolean);
|
||||||
|
|
||||||
|
if (shortName && isShortName(shortName)) {
|
||||||
|
return convertShortName(shortName, parseInt(skinTone, 10));
|
||||||
|
}
|
||||||
|
|
||||||
|
return m;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCountOfAllMatches(str: string, regex: RegExp) {
|
function getCountOfAllMatches(str: string, regex: RegExp) {
|
||||||
|
@ -299,17 +305,12 @@ data.forEach(emoji => {
|
||||||
}
|
}
|
||||||
|
|
||||||
imageByEmoji[convertShortName(short_name)] = makeImagePath(image);
|
imageByEmoji[convertShortName(short_name)] = makeImagePath(image);
|
||||||
dataByEmoji[convertShortName(short_name)] = { shortName: short_name };
|
|
||||||
|
|
||||||
if (skin_variations) {
|
if (skin_variations) {
|
||||||
Object.entries(skin_variations).forEach(([tone, variation]) => {
|
Object.entries(skin_variations).forEach(([tone, variation]) => {
|
||||||
imageByEmoji[
|
imageByEmoji[
|
||||||
convertShortName(short_name, tone as SkinToneKey)
|
convertShortName(short_name, tone as SkinToneKey)
|
||||||
] = makeImagePath(variation.image);
|
] = makeImagePath(variation.image);
|
||||||
dataByEmoji[convertShortName(short_name, tone as SkinToneKey)] = {
|
|
||||||
shortName: short_name,
|
|
||||||
tone: tone as SkinToneKey,
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue