diff --git a/webapp/src/components/markdownEditorInput/markdownEditorInput.tsx b/webapp/src/components/markdownEditorInput/markdownEditorInput.tsx index 6bfee2d55..f687e01e5 100644 --- a/webapp/src/components/markdownEditorInput/markdownEditorInput.tsx +++ b/webapp/src/components/markdownEditorInput/markdownEditorInput.tsx @@ -10,7 +10,7 @@ import createMentionPlugin, { import '@draft-js-plugins/mention/lib/plugin.css' import {ContentState, DraftHandleValue, EditorState, getDefaultKeyBinding} from 'draft-js' import React, { - ReactElement, useCallback, useEffect, + ReactElement, useCallback, useMemo, useRef, useState, } from 'react' @@ -46,24 +46,7 @@ const MarkdownEditorInput = (props: Props): ReactElement => { return EditorState.moveSelectionToEnd(state) } - const [editorState, setEditorState] = useState(() => { - return generateEditorState(initialText) - }) - - const [initialTextCache, setInitialTextCache] = useState(initialText) - - // avoiding stale closure - useEffect(() => { - // only change editor state when initialText actually changes from one defined value to another. - // This is needed to make the mentions plugin work. For some reason, if we don't check - // for this if condition here, mentions don't work. I suspect it's because without - // the in condition, we're changing editor state twice during component initialization - // and for some reason it causes mentions to not show up. - if (initialText && initialText !== initialTextCache) { - setEditorState(generateEditorState(initialText || '')) - setInitialTextCache(initialText) - } - }, [initialText]) + const [editorState, setEditorState] = useState(() => generateEditorState(initialText)) const [isMentionPopoverOpen, setIsMentionPopoverOpen] = useState(false) const [isEmojiPopoverOpen, setIsEmojiPopoverOpen] = useState(false) @@ -87,16 +70,13 @@ const MarkdownEditorInput = (props: Props): ReactElement => { return {plugins, MentionSuggestions, EmojiSuggestions} }, []) - useEffect(() => { - if (isEditing) { - if (initialText === '') { - setEditorState(EditorState.createEmpty()) - } else { - setEditorState(EditorState.moveSelectionToEnd(editorState)) - } - setTimeout(() => ref.current?.focus(), 200) - } - }, [isEditing, initialText]) + const onEditorStateChange = useCallback((newEditorState: EditorState) => { + // newEditorState. + const newText = newEditorState.getCurrentContent().getPlainText() + + onChange && onChange(newText) + setEditorState(newEditorState) + }, [onChange]) const customKeyBindingFn = useCallback((e: React.KeyboardEvent) => { if (isMentionPopoverOpen || isEmojiPopoverOpen) { @@ -107,14 +87,36 @@ const MarkdownEditorInput = (props: Props): ReactElement => { return 'editor-blur' } + if(getDefaultKeyBinding(e) === 'undo'){ + return 'editor-undo' + } + + if(getDefaultKeyBinding(e) === 'redo'){ + return 'editor-redo' + } + return getDefaultKeyBinding(e as any) }, [isEmojiPopoverOpen, isMentionPopoverOpen]) - const handleKeyCommand = useCallback((command: string): DraftHandleValue => { + const handleKeyCommand = useCallback((command: string, currentState: EditorState): DraftHandleValue => { if (command === 'editor-blur') { ref.current?.blur() return 'handled' } + + if(command === 'editor-redo'){ + const selectionRemovedState = EditorState.redo(currentState) + onEditorStateChange(EditorState.redo(selectionRemovedState)) + + return 'handled' + } + + if(command === 'editor-undo'){ + const selectionRemovedState = EditorState.undo(currentState) + onEditorStateChange(EditorState.undo(selectionRemovedState)) + + return 'handled' + } return 'not-handled' }, []) @@ -124,13 +126,6 @@ const MarkdownEditorInput = (props: Props): ReactElement => { onBlur && onBlur(text) }, [editorState, onBlur]) - const onEditorStateChange = useCallback((newEditorState: EditorState) => { - const newText = newEditorState.getCurrentContent().getPlainText() - - onChange && onChange(newText) - setEditorState(newEditorState) - }, [onChange]) - const onMentionPopoverOpenChange = useCallback((open: boolean) => { setIsMentionPopoverOpen(open) }, [])