|
@@ -1,6 +1,6 @@
|
|
import { useCallback, useContext, useMemo } from 'react';
|
|
import { useCallback, useContext, useMemo } from 'react';
|
|
import { Editor } from 'slate';
|
|
import { Editor } from 'slate';
|
|
-import { TextDelta, TextSelection } from '$app/interfaces/document';
|
|
|
|
|
|
+import { TextBlockKeyEventHandlerParams, TextDelta, TextSelection } from '$app/interfaces/document';
|
|
import { useTextInput } from '../_shared/TextInput.hooks';
|
|
import { useTextInput } from '../_shared/TextInput.hooks';
|
|
import { useAppDispatch } from '@/appflowy_app/stores/store';
|
|
import { useAppDispatch } from '@/appflowy_app/stores/store';
|
|
import { DocumentControllerContext } from '@/appflowy_app/stores/effects/document/document_controller';
|
|
import { DocumentControllerContext } from '@/appflowy_app/stores/effects/document/document_controller';
|
|
@@ -8,22 +8,24 @@ import {
|
|
backspaceNodeThunk,
|
|
backspaceNodeThunk,
|
|
indentNodeThunk,
|
|
indentNodeThunk,
|
|
splitNodeThunk,
|
|
splitNodeThunk,
|
|
-} from '@/appflowy_app/stores/reducers/document/async_actions';
|
|
|
|
|
|
+ setCursorNextLineThunk,
|
|
|
|
+ setCursorPreLineThunk,
|
|
|
|
+} from '@/appflowy_app/stores/reducers/document/async-actions';
|
|
import { documentActions } from '@/appflowy_app/stores/reducers/document/slice';
|
|
import { documentActions } from '@/appflowy_app/stores/reducers/document/slice';
|
|
import {
|
|
import {
|
|
- triggerHotkey,
|
|
|
|
- canHandleEnterKey,
|
|
|
|
canHandleBackspaceKey,
|
|
canHandleBackspaceKey,
|
|
- canHandleTabKey,
|
|
|
|
- onHandleEnterKey,
|
|
|
|
- keyBoardEventKeyMap,
|
|
|
|
- canHandleUpKey,
|
|
|
|
canHandleDownKey,
|
|
canHandleDownKey,
|
|
|
|
+ canHandleEnterKey,
|
|
canHandleLeftKey,
|
|
canHandleLeftKey,
|
|
canHandleRightKey,
|
|
canHandleRightKey,
|
|
-} from '@/appflowy_app/utils/slate/hotkey';
|
|
|
|
-import { updateNodeDeltaThunk } from '$app/stores/reducers/document/async_actions/update';
|
|
|
|
-import { setCursorPreLineThunk, setCursorNextLineThunk } from '$app/stores/reducers/document/async_actions/set_cursor';
|
|
|
|
|
|
+ canHandleTabKey,
|
|
|
|
+ canHandleUpKey,
|
|
|
|
+ onHandleEnterKey,
|
|
|
|
+ triggerHotkey,
|
|
|
|
+} from '$app/utils/document/slate/hotkey';
|
|
|
|
+import { updateNodeDeltaThunk } from '$app_reducers/document/async-actions/blocks/text/update';
|
|
|
|
+import { useMarkDown } from './useMarkDown.hooks';
|
|
|
|
+import { keyBoardEventKeyMap } from '$app/constants/document/text_block';
|
|
|
|
|
|
export function useTextBlock(id: string) {
|
|
export function useTextBlock(id: string) {
|
|
const { editor, onChange, value } = useTextInput(id);
|
|
const { editor, onChange, value } = useTextInput(id);
|
|
@@ -54,25 +56,15 @@ export function useTextBlock(id: string) {
|
|
};
|
|
};
|
|
}
|
|
}
|
|
|
|
|
|
-type TextBlockKeyEventHandlerParams = [React.KeyboardEvent<HTMLDivElement>, Editor];
|
|
|
|
-
|
|
|
|
function useTextBlockKeyEvent(id: string, editor: Editor) {
|
|
function useTextBlockKeyEvent(id: string, editor: Editor) {
|
|
const { indentAction, backSpaceAction, splitAction, wrapAction, focusPreLineAction, focusNextLineAction } =
|
|
const { indentAction, backSpaceAction, splitAction, wrapAction, focusPreLineAction, focusNextLineAction } =
|
|
useActions(id);
|
|
useActions(id);
|
|
|
|
|
|
- const dispatch = useAppDispatch();
|
|
|
|
- const keepSelection = useCallback(() => {
|
|
|
|
- // This is a hack to make sure the selection is updated after next render
|
|
|
|
- // It will save the selection to the store, and the selection will be restored
|
|
|
|
- if (!editor.selection || !editor.selection.anchor || !editor.selection.focus) return;
|
|
|
|
- const { anchor, focus } = editor.selection;
|
|
|
|
- const selection = { anchor, focus } as TextSelection;
|
|
|
|
- dispatch(documentActions.setTextSelection({ blockId: id, selection }));
|
|
|
|
- }, [editor]);
|
|
|
|
|
|
+ const { markdownEvents } = useMarkDown(id);
|
|
|
|
|
|
const enterEvent = useMemo(() => {
|
|
const enterEvent = useMemo(() => {
|
|
return {
|
|
return {
|
|
- key: keyBoardEventKeyMap.Enter,
|
|
|
|
|
|
+ triggerEventKey: keyBoardEventKeyMap.Enter,
|
|
canHandle: canHandleEnterKey,
|
|
canHandle: canHandleEnterKey,
|
|
handler: (...args: TextBlockKeyEventHandlerParams) => {
|
|
handler: (...args: TextBlockKeyEventHandlerParams) => {
|
|
onHandleEnterKey(...args, {
|
|
onHandleEnterKey(...args, {
|
|
@@ -85,29 +77,27 @@ function useTextBlockKeyEvent(id: string, editor: Editor) {
|
|
|
|
|
|
const tabEvent = useMemo(() => {
|
|
const tabEvent = useMemo(() => {
|
|
return {
|
|
return {
|
|
- key: keyBoardEventKeyMap.Tab,
|
|
|
|
|
|
+ triggerEventKey: keyBoardEventKeyMap.Tab,
|
|
canHandle: canHandleTabKey,
|
|
canHandle: canHandleTabKey,
|
|
handler: (..._args: TextBlockKeyEventHandlerParams) => {
|
|
handler: (..._args: TextBlockKeyEventHandlerParams) => {
|
|
- keepSelection();
|
|
|
|
void indentAction();
|
|
void indentAction();
|
|
},
|
|
},
|
|
};
|
|
};
|
|
- }, [keepSelection, indentAction]);
|
|
|
|
|
|
+ }, [indentAction]);
|
|
|
|
|
|
const backSpaceEvent = useMemo(() => {
|
|
const backSpaceEvent = useMemo(() => {
|
|
return {
|
|
return {
|
|
- key: keyBoardEventKeyMap.Backspace,
|
|
|
|
|
|
+ triggerEventKey: keyBoardEventKeyMap.Backspace,
|
|
canHandle: canHandleBackspaceKey,
|
|
canHandle: canHandleBackspaceKey,
|
|
handler: (..._args: TextBlockKeyEventHandlerParams) => {
|
|
handler: (..._args: TextBlockKeyEventHandlerParams) => {
|
|
- keepSelection();
|
|
|
|
void backSpaceAction();
|
|
void backSpaceAction();
|
|
},
|
|
},
|
|
};
|
|
};
|
|
- }, [keepSelection, backSpaceAction]);
|
|
|
|
|
|
+ }, [backSpaceAction]);
|
|
|
|
|
|
const upEvent = useMemo(() => {
|
|
const upEvent = useMemo(() => {
|
|
return {
|
|
return {
|
|
- key: keyBoardEventKeyMap.Up,
|
|
|
|
|
|
+ triggerEventKey: keyBoardEventKeyMap.Up,
|
|
canHandle: canHandleUpKey,
|
|
canHandle: canHandleUpKey,
|
|
handler: (...args: TextBlockKeyEventHandlerParams) => {
|
|
handler: (...args: TextBlockKeyEventHandlerParams) => {
|
|
void focusPreLineAction({
|
|
void focusPreLineAction({
|
|
@@ -119,7 +109,7 @@ function useTextBlockKeyEvent(id: string, editor: Editor) {
|
|
|
|
|
|
const downEvent = useMemo(() => {
|
|
const downEvent = useMemo(() => {
|
|
return {
|
|
return {
|
|
- key: keyBoardEventKeyMap.Down,
|
|
|
|
|
|
+ triggerEventKey: keyBoardEventKeyMap.Down,
|
|
canHandle: canHandleDownKey,
|
|
canHandle: canHandleDownKey,
|
|
handler: (...args: TextBlockKeyEventHandlerParams) => {
|
|
handler: (...args: TextBlockKeyEventHandlerParams) => {
|
|
void focusNextLineAction({
|
|
void focusNextLineAction({
|
|
@@ -131,7 +121,7 @@ function useTextBlockKeyEvent(id: string, editor: Editor) {
|
|
|
|
|
|
const leftEvent = useMemo(() => {
|
|
const leftEvent = useMemo(() => {
|
|
return {
|
|
return {
|
|
- key: keyBoardEventKeyMap.Left,
|
|
|
|
|
|
+ triggerEventKey: keyBoardEventKeyMap.Left,
|
|
canHandle: canHandleLeftKey,
|
|
canHandle: canHandleLeftKey,
|
|
handler: (...args: TextBlockKeyEventHandlerParams) => {
|
|
handler: (...args: TextBlockKeyEventHandlerParams) => {
|
|
void focusPreLineAction({
|
|
void focusPreLineAction({
|
|
@@ -144,7 +134,7 @@ function useTextBlockKeyEvent(id: string, editor: Editor) {
|
|
|
|
|
|
const rightEvent = useMemo(() => {
|
|
const rightEvent = useMemo(() => {
|
|
return {
|
|
return {
|
|
- key: keyBoardEventKeyMap.Right,
|
|
|
|
|
|
+ triggerEventKey: keyBoardEventKeyMap.Right,
|
|
canHandle: canHandleRightKey,
|
|
canHandle: canHandleRightKey,
|
|
handler: (...args: TextBlockKeyEventHandlerParams) => {
|
|
handler: (...args: TextBlockKeyEventHandlerParams) => {
|
|
void focusNextLineAction({
|
|
void focusNextLineAction({
|
|
@@ -159,6 +149,8 @@ function useTextBlockKeyEvent(id: string, editor: Editor) {
|
|
(event: React.KeyboardEvent<HTMLDivElement>) => {
|
|
(event: React.KeyboardEvent<HTMLDivElement>) => {
|
|
// This is list of key events that can be handled by TextBlock
|
|
// This is list of key events that can be handled by TextBlock
|
|
const keyEvents = [enterEvent, backSpaceEvent, tabEvent, upEvent, downEvent, leftEvent, rightEvent];
|
|
const keyEvents = [enterEvent, backSpaceEvent, tabEvent, upEvent, downEvent, leftEvent, rightEvent];
|
|
|
|
+
|
|
|
|
+ keyEvents.push(...markdownEvents);
|
|
const matchKey = keyEvents.find((keyEvent) => keyEvent.canHandle(event, editor));
|
|
const matchKey = keyEvents.find((keyEvent) => keyEvent.canHandle(event, editor));
|
|
if (!matchKey) {
|
|
if (!matchKey) {
|
|
triggerHotkey(event, editor);
|
|
triggerHotkey(event, editor);
|
|
@@ -169,7 +161,7 @@ function useTextBlockKeyEvent(id: string, editor: Editor) {
|
|
event.preventDefault();
|
|
event.preventDefault();
|
|
matchKey.handler(event, editor);
|
|
matchKey.handler(event, editor);
|
|
},
|
|
},
|
|
- [editor, enterEvent, backSpaceEvent, tabEvent, upEvent, downEvent, leftEvent, rightEvent]
|
|
|
|
|
|
+ [editor, enterEvent, backSpaceEvent, tabEvent, upEvent, downEvent, leftEvent, rightEvent, markdownEvents]
|
|
);
|
|
);
|
|
|
|
|
|
return {
|
|
return {
|