fix undo/redo/cut

This commit is contained in:
kyeongsoosoo 2022-04-19 01:37:06 +09:00
parent bb7ee3851c
commit 921a1369b2

View file

@ -10,7 +10,7 @@ import createMentionPlugin, {
import '@draft-js-plugins/mention/lib/plugin.css' import '@draft-js-plugins/mention/lib/plugin.css'
import {ContentState, DraftHandleValue, EditorState, getDefaultKeyBinding} from 'draft-js' import {ContentState, DraftHandleValue, EditorState, getDefaultKeyBinding} from 'draft-js'
import React, { import React, {
ReactElement, useCallback, useEffect, ReactElement, useCallback,
useMemo, useRef, useMemo, useRef,
useState, useState,
} from 'react' } from 'react'
@ -46,24 +46,7 @@ const MarkdownEditorInput = (props: Props): ReactElement => {
return EditorState.moveSelectionToEnd(state) return EditorState.moveSelectionToEnd(state)
} }
const [editorState, setEditorState] = useState(() => { const [editorState, setEditorState] = useState(() => generateEditorState(initialText))
return generateEditorState(initialText)
})
const [initialTextCache, setInitialTextCache] = useState<string | undefined>(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 [isMentionPopoverOpen, setIsMentionPopoverOpen] = useState(false) const [isMentionPopoverOpen, setIsMentionPopoverOpen] = useState(false)
const [isEmojiPopoverOpen, setIsEmojiPopoverOpen] = useState(false) const [isEmojiPopoverOpen, setIsEmojiPopoverOpen] = useState(false)
@ -87,16 +70,13 @@ const MarkdownEditorInput = (props: Props): ReactElement => {
return {plugins, MentionSuggestions, EmojiSuggestions} return {plugins, MentionSuggestions, EmojiSuggestions}
}, []) }, [])
useEffect(() => { const onEditorStateChange = useCallback((newEditorState: EditorState) => {
if (isEditing) { // newEditorState.
if (initialText === '') { const newText = newEditorState.getCurrentContent().getPlainText()
setEditorState(EditorState.createEmpty())
} else { onChange && onChange(newText)
setEditorState(EditorState.moveSelectionToEnd(editorState)) setEditorState(newEditorState)
} }, [onChange])
setTimeout(() => ref.current?.focus(), 200)
}
}, [isEditing, initialText])
const customKeyBindingFn = useCallback((e: React.KeyboardEvent) => { const customKeyBindingFn = useCallback((e: React.KeyboardEvent) => {
if (isMentionPopoverOpen || isEmojiPopoverOpen) { if (isMentionPopoverOpen || isEmojiPopoverOpen) {
@ -107,15 +87,37 @@ const MarkdownEditorInput = (props: Props): ReactElement => {
return 'editor-blur' return 'editor-blur'
} }
if(getDefaultKeyBinding(e) === 'undo'){
return 'editor-undo'
}
if(getDefaultKeyBinding(e) === 'redo'){
return 'editor-redo'
}
return getDefaultKeyBinding(e as any) return getDefaultKeyBinding(e as any)
}, [isEmojiPopoverOpen, isMentionPopoverOpen]) }, [isEmojiPopoverOpen, isMentionPopoverOpen])
const handleKeyCommand = useCallback((command: string): DraftHandleValue => { const handleKeyCommand = useCallback((command: string, currentState: EditorState): DraftHandleValue => {
if (command === 'editor-blur') { if (command === 'editor-blur') {
ref.current?.blur() ref.current?.blur()
return 'handled' 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' return 'not-handled'
}, []) }, [])
@ -124,13 +126,6 @@ const MarkdownEditorInput = (props: Props): ReactElement => {
onBlur && onBlur(text) onBlur && onBlur(text)
}, [editorState, onBlur]) }, [editorState, onBlur])
const onEditorStateChange = useCallback((newEditorState: EditorState) => {
const newText = newEditorState.getCurrentContent().getPlainText()
onChange && onChange(newText)
setEditorState(newEditorState)
}, [onChange])
const onMentionPopoverOpenChange = useCallback((open: boolean) => { const onMentionPopoverOpenChange = useCallback((open: boolean) => {
setIsMentionPopoverOpen(open) setIsMentionPopoverOpen(open)
}, []) }, [])