From 308adef98dc9c3526fa41432ab3ebc686eeac434 Mon Sep 17 00:00:00 2001 From: email Date: Tue, 11 Jan 2022 21:20:33 +0800 Subject: [PATCH] refactor: editor tools --- web/src/components/Editor/Editor.tsx | 19 +++----- web/src/components/MemoEditor.tsx | 62 +++++++++++++------------- web/src/components/common/OnlyWhen.tsx | 4 +- 3 files changed, 38 insertions(+), 47 deletions(-) diff --git a/web/src/components/Editor/Editor.tsx b/web/src/components/Editor/Editor.tsx index d43c59b6..42aa3492 100644 --- a/web/src/components/Editor/Editor.tsx +++ b/web/src/components/Editor/Editor.tsx @@ -1,4 +1,4 @@ -import { forwardRef, useCallback, useContext, useEffect, useImperativeHandle, useRef } from "react"; +import { forwardRef, ReactNode, useCallback, useContext, useEffect, useImperativeHandle, useRef } from "react"; import TinyUndo from "tiny-undo"; import appContext from "../../stores/appContext"; import { storage } from "../../helpers/storage"; @@ -14,17 +14,15 @@ export interface EditorRefActions { getContent: () => string; } -export interface EditorProps { +interface EditorProps { className: string; initialContent: string; placeholder: string; showConfirmBtn: boolean; showCancelBtn: boolean; - showTools: boolean; + tools?: ReactNode; onConfirmBtnClick: (content: string) => void; onCancelBtnClick: () => void; - onTagTextBtnClick: () => void; - onUploadFileBtnClick: () => void; onContentChange: (content: string) => void; } @@ -39,15 +37,13 @@ const Editor = forwardRef((props: EditorProps, ref: React.ForwardedRef(null); const tinyUndoRef = useRef(null); + // NOTE: auto-justify textarea height const refresh = useRefresh(); useEffect(() => { @@ -175,12 +171,7 @@ const Editor = forwardRef((props: EditorProps, ref: React.ForwardedRef
- - <> - - - - + {props.tools}
diff --git a/web/src/components/MemoEditor.tsx b/web/src/components/MemoEditor.tsx index ece2430f..2622fe36 100644 --- a/web/src/components/MemoEditor.tsx +++ b/web/src/components/MemoEditor.tsx @@ -5,7 +5,7 @@ import utils from "../helpers/utils"; import { storage } from "../helpers/storage"; import useToggle from "../hooks/useToggle"; import toastHelper from "./Toast"; -import Editor, { EditorProps, EditorRefActions } from "./Editor/Editor"; +import Editor, { EditorRefActions } from "./Editor/Editor"; import "../less/memo-editor.less"; const getCursorPostion = (input: HTMLTextAreaElement) => { @@ -20,7 +20,6 @@ const getCursorPostion = (input: HTMLTextAreaElement) => { div.style.visibility = "hidden"; div.style.whiteSpace = "pre-wrap"; - // we need a character that will replace whitespace when filling our dummy element if it's a single line const swap = "."; const inputValue = input.tagName === "INPUT" ? input.value.replace(/ /g, swap) : input.value; const textContent = inputValue.substring(0, selectionPoint || 0); @@ -100,9 +99,7 @@ const MemoEditor: React.FC = () => { }; const handleClickEvent = () => { - setTimeout(() => { - handleContentChange(editorRef.current?.element.value ?? ""); - }); + handleContentChange(editorRef.current?.element.value ?? ""); }; const handleKeyDownEvent = () => { @@ -184,20 +181,18 @@ const MemoEditor: React.FC = () => { setEditorContentCache(content); if (editorRef.current) { - const currentValue = editorRef.current.getContent(); const selectionStart = editorRef.current.element.selectionStart; - const prevString = currentValue.slice(0, selectionStart); + const prevString = content.slice(0, selectionStart); + const nextString = content.slice(selectionStart); - if (prevString.endsWith("#")) { + if (prevString.endsWith("#") && (nextString.startsWith(" ") || nextString === "")) { toggleTagSeletor(true); updateTagSelectorPopupPosition(); } else { toggleTagSeletor(false); } - setTimeout(() => { - editorRef.current?.focus(); - }); + editorRef.current?.focus(); } }, []); @@ -219,16 +214,10 @@ const MemoEditor: React.FC = () => { cursorIndex = prevString.length - 1; } - setTimeout(() => { - if (!editorRef.current) { - return; - } - - editorRef.current.element.value = nextValue; - editorRef.current.element.setSelectionRange(cursorIndex, cursorIndex); - editorRef.current.focus(); - handleContentChange(editorRef.current.element.value); - }); + editorRef.current.element.value = nextValue; + editorRef.current.element.setSelectionRange(cursorIndex, cursorIndex); + editorRef.current.focus(); + handleContentChange(editorRef.current.element.value); }, []); const updateTagSelectorPopupPosition = useCallback(() => { @@ -236,13 +225,15 @@ const MemoEditor: React.FC = () => { return; } + const seletorPopupWidth = 128; + const editorWidth = editorRef.current.element.clientWidth; const { x, y } = getCursorPostion(editorRef.current.element); - if (x + 128 + 16 > editorRef.current.element.clientWidth) { - tagSeletorRef.current.style.left = `${editorRef.current.element.clientWidth + 20 - 128}px`; - } else { - tagSeletorRef.current.style.left = `${x + 2}px`; - } - tagSeletorRef.current.style.top = `${y + 32 + 6}px`; + const left = x + seletorPopupWidth + 16 > editorWidth ? editorWidth + 20 - seletorPopupWidth : x + 2; + const top = y + 32 + 6; + + tagSeletorRef.current.scroll(0, 0); + tagSeletorRef.current.style.left = `${left}px`; + tagSeletorRef.current.style.top = `${top}px`; }, []); const handleUploadFileBtnClick = useCallback(() => { @@ -267,23 +258,21 @@ const MemoEditor: React.FC = () => { const handleTagSeletorClick = useCallback((event: React.MouseEvent) => { if (tagSeletorRef.current !== event.target && tagSeletorRef.current?.contains(event.target as Node)) { editorRef.current?.insertText((event.target as HTMLElement).textContent ?? ""); + toggleTagSeletor(false); } }, []); const showEditStatus = Boolean(globalState.editMemoId); - const editorConfig: EditorProps = useMemo( + const editorConfig = useMemo( () => ({ className: "memo-editor", initialContent: getEditorContentCache(), placeholder: "现在的想法是...", showConfirmBtn: true, showCancelBtn: showEditStatus, - showTools: true, onConfirmBtnClick: handleSaveBtnClick, onCancelBtnClick: handleCancelBtnClick, - onTagTextBtnClick: handleTagTextBtnClick, - onUploadFileBtnClick: handleUploadFileBtnClick, onContentChange: handleContentChange, }), [showEditStatus] @@ -292,7 +281,16 @@ const MemoEditor: React.FC = () => { return (

正在修改中...

- + + + + + } + />
0 ? "" : "hidden"}`} diff --git a/web/src/components/common/OnlyWhen.tsx b/web/src/components/common/OnlyWhen.tsx index 74ec8d19..c366fbea 100644 --- a/web/src/components/common/OnlyWhen.tsx +++ b/web/src/components/common/OnlyWhen.tsx @@ -1,5 +1,7 @@ +import { ReactNode } from "react"; + interface OnlyWhenProps { - children: React.ReactElement; + children: ReactNode; when: boolean; }