mirror of
https://github.com/usememos/memos.git
synced 2025-06-05 22:09:59 +02:00
chore: update IME mode checks
This commit is contained in:
@ -1,6 +1,7 @@
|
|||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { forwardRef, ReactNode, useCallback, useEffect, useImperativeHandle, useRef } from "react";
|
import { last } from "lodash-es";
|
||||||
import { useAutoComplete } from "../hooks";
|
import { forwardRef, ReactNode, useCallback, useEffect, useImperativeHandle, useRef, useState } from "react";
|
||||||
|
import { NodeType, OrderedListNode, TaskListNode, UnorderedListNode } from "@/types/node";
|
||||||
import TagSuggestions from "./TagSuggestions";
|
import TagSuggestions from "./TagSuggestions";
|
||||||
|
|
||||||
export interface EditorRefActions {
|
export interface EditorRefActions {
|
||||||
@ -30,6 +31,7 @@ interface Props {
|
|||||||
|
|
||||||
const Editor = forwardRef(function Editor(props: Props, ref: React.ForwardedRef<EditorRefActions>) {
|
const Editor = forwardRef(function Editor(props: Props, ref: React.ForwardedRef<EditorRefActions>) {
|
||||||
const { className, initialContent, placeholder, onPaste, onContentChange: handleContentChangeCallback } = props;
|
const { className, initialContent, placeholder, onPaste, onContentChange: handleContentChangeCallback } = props;
|
||||||
|
const [isInIME, setIsInIME] = useState(false);
|
||||||
const editorRef = useRef<HTMLTextAreaElement>(null);
|
const editorRef = useRef<HTMLTextAreaElement>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -133,8 +135,6 @@ const Editor = forwardRef(function Editor(props: Props, ref: React.ForwardedRef<
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
useAutoComplete(editorActions);
|
|
||||||
|
|
||||||
useImperativeHandle(ref, () => editorActions, []);
|
useImperativeHandle(ref, () => editorActions, []);
|
||||||
|
|
||||||
const updateEditorHeight = () => {
|
const updateEditorHeight = () => {
|
||||||
@ -149,6 +149,33 @@ const Editor = forwardRef(function Editor(props: Props, ref: React.ForwardedRef<
|
|||||||
updateEditorHeight();
|
updateEditorHeight();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const handleEditorKeyDown = (event: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
||||||
|
if (event.key === "Enter" && !isInIME) {
|
||||||
|
const cursorPosition = editorActions.getCursorPosition();
|
||||||
|
const prevContent = editorActions.getContent().substring(0, cursorPosition);
|
||||||
|
const lastNode = last(window.parse(prevContent));
|
||||||
|
if (!lastNode) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let insertText = "";
|
||||||
|
if (lastNode.type === NodeType.TASK_LIST) {
|
||||||
|
const { complete } = lastNode.value as TaskListNode;
|
||||||
|
insertText = complete ? "- [x] " : "- [ ] ";
|
||||||
|
} else if (lastNode.type === NodeType.UNORDERED_LIST) {
|
||||||
|
const { symbol } = lastNode.value as UnorderedListNode;
|
||||||
|
insertText = `${symbol} `;
|
||||||
|
} else if (lastNode.type === NodeType.ORDERED_LIST) {
|
||||||
|
const { number } = lastNode.value as OrderedListNode;
|
||||||
|
insertText = `${Number(number) + 1}. `;
|
||||||
|
}
|
||||||
|
if (insertText) {
|
||||||
|
editorActions.insertText(`\n${insertText}`);
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={classNames(
|
className={classNames(
|
||||||
@ -163,6 +190,9 @@ const Editor = forwardRef(function Editor(props: Props, ref: React.ForwardedRef<
|
|||||||
ref={editorRef}
|
ref={editorRef}
|
||||||
onPaste={onPaste}
|
onPaste={onPaste}
|
||||||
onInput={handleEditorInput}
|
onInput={handleEditorInput}
|
||||||
|
onKeyDown={handleEditorKeyDown}
|
||||||
|
onCompositionStart={() => setIsInIME(true)}
|
||||||
|
onCompositionEnd={() => setTimeout(() => setIsInIME(false))}
|
||||||
></textarea>
|
></textarea>
|
||||||
<TagSuggestions editorRef={editorRef} editorActions={ref} />
|
<TagSuggestions editorRef={editorRef} editorActions={ref} />
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
import useAutoComplete from "./useAutoComplete";
|
|
||||||
|
|
||||||
export { useAutoComplete };
|
|
@ -1,43 +0,0 @@
|
|||||||
import { last } from "lodash-es";
|
|
||||||
import { useEffect } from "react";
|
|
||||||
import { NodeType, OrderedListNode, TaskListNode, UnorderedListNode } from "@/types/node";
|
|
||||||
import { EditorRefActions } from "../Editor";
|
|
||||||
|
|
||||||
const useAutoComplete = (actions: EditorRefActions) => {
|
|
||||||
useEffect(() => {
|
|
||||||
const editor = actions.getEditor();
|
|
||||||
if (!editor) return;
|
|
||||||
|
|
||||||
editor.addEventListener("keydown", (event) => {
|
|
||||||
if (event.key === "Enter") {
|
|
||||||
if (event.isComposing) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const cursorPosition = actions.getCursorPosition();
|
|
||||||
const prevContent = actions.getContent().substring(0, cursorPosition);
|
|
||||||
const lastNode = last(window.parse(prevContent));
|
|
||||||
if (!lastNode) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let insertText = "";
|
|
||||||
if (lastNode.type === NodeType.TASK_LIST) {
|
|
||||||
const { complete } = lastNode.value as TaskListNode;
|
|
||||||
insertText = complete ? "- [x] " : "- [ ] ";
|
|
||||||
} else if (lastNode.type === NodeType.UNORDERED_LIST) {
|
|
||||||
const { symbol } = lastNode.value as UnorderedListNode;
|
|
||||||
insertText = `${symbol} `;
|
|
||||||
} else if (lastNode.type === NodeType.ORDERED_LIST) {
|
|
||||||
const { number } = lastNode.value as OrderedListNode;
|
|
||||||
insertText = `${Number(number) + 1}. `;
|
|
||||||
}
|
|
||||||
if (insertText) {
|
|
||||||
actions.insertText(`\n${insertText}`);
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, []);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default useAutoComplete;
|
|
Reference in New Issue
Block a user