From 7308265774860e56fafcd797c310ea478146276e Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 14 Dec 2023 14:32:50 +0800 Subject: [PATCH 1/6] select node after code-view typing --- src/_redux/main/context.ts | 4 ++ src/_redux/main/nodeTree/slice.ts | 11 +++- src/_redux/main/nodeTree/types.ts | 4 +- src/_redux/main/types.ts | 2 + src/_redux/useAppState.tsx | 2 + .../nodeTreeView/NodeTreeView.tsx | 14 ++-- .../nodeTreeView/hooks/useCmdk.ts | 5 +- ...nsHandlers.ts => useNodeActionHandlers.ts} | 12 +--- .../nodeTreeView/hooks/useNodeTreeCallback.ts | 4 +- src/components/main/codeView/CodeView.tsx | 10 +-- src/components/main/codeView/helpers.ts | 42 ++++++++++++ .../main/codeView/hooks/useEditor.ts | 64 +++++-------------- src/components/main/codeView/index.ts | 1 + src/pages/main/MainPage.tsx | 4 ++ src/pages/main/hooks/useReferences.ts | 29 +++++---- .../main/processor/hooks/useNodeTreeEvent.ts | 42 +++++++++--- 16 files changed, 152 insertions(+), 98 deletions(-) rename src/components/main/actionsPanel/nodeTreeView/hooks/{useNodeActionsHandlers.ts => useNodeActionHandlers.ts} (99%) diff --git a/src/_redux/main/context.ts b/src/_redux/main/context.ts index 66b0e21e..a185d85b 100644 --- a/src/_redux/main/context.ts +++ b/src/_redux/main/context.ts @@ -27,6 +27,10 @@ export const MainContext: Context = createContext({ current: false, }, setIsContentProgrammaticallyChanged: () => {}, + isCodeTyping: { + current: false, + }, + setIsCodeTyping: () => {}, importProject: () => {}, onUndo: () => {}, diff --git a/src/_redux/main/nodeTree/slice.ts b/src/_redux/main/nodeTree/slice.ts index 972bc196..1e10bdf7 100644 --- a/src/_redux/main/nodeTree/slice.ts +++ b/src/_redux/main/nodeTree/slice.ts @@ -3,12 +3,14 @@ import { createSlice, PayloadAction } from "@reduxjs/toolkit"; import { TUpdateTreeViewStatePayload } from "../types"; import { TNodeTreeReducerState } from "./types"; +import { TCodeSelection } from "@_components/main/codeView"; const nodeTreeReducerInitialState: TNodeTreeReducerState = { nodeTree: {}, validNodeTree: {}, - needToSelectNodePaths: [], + needToSelectNodePaths: null, + needToSelectCode: null, nodeTreeViewState: { focusedItem: "", @@ -32,10 +34,14 @@ const nodeTreeSlice = createSlice({ state.validNodeTree = validNodeTree; }, - setNeedToSelectNodePaths(state, action: PayloadAction) { + setNeedToSelectNodePaths(state, action: PayloadAction) { const needToSelectNodePaths = action.payload; state.needToSelectNodePaths = needToSelectNodePaths; }, + setNeedToSelectCode(state, action: PayloadAction) { + const needToSelectCode = action.payload; + state.needToSelectCode = needToSelectCode; + }, focusNodeTreeNode(state, action: PayloadAction) { const focusedItem = action.payload; @@ -146,6 +152,7 @@ export const { setValidNodeTree, setNeedToSelectNodePaths, + setNeedToSelectCode, focusNodeTreeNode, setExpandedNodeTreeNodes, diff --git a/src/_redux/main/nodeTree/types.ts b/src/_redux/main/nodeTree/types.ts index 4fe0c892..ce311bfe 100644 --- a/src/_redux/main/nodeTree/types.ts +++ b/src/_redux/main/nodeTree/types.ts @@ -1,12 +1,14 @@ import { TNodeTreeData, TNodeUid } from "@_node/types"; import { TTreeViewState } from "../types"; +import { TCodeSelection } from "@_components/main/codeView"; export type TNodeTreeReducerState = { nodeTree: TNodeTreeData; validNodeTree: TNodeTreeData; - needToSelectNodePaths: string[]; + needToSelectNodePaths: string[] | null; + needToSelectCode: TCodeSelection | null; nodeTreeViewState: TTreeViewState; hoveredNodeUid: TNodeUid; diff --git a/src/_redux/main/types.ts b/src/_redux/main/types.ts index cc64646a..b81adda7 100644 --- a/src/_redux/main/types.ts +++ b/src/_redux/main/types.ts @@ -58,6 +58,8 @@ export type TMainContext = { setIframeRefRef: (iframeRef: HTMLIFrameElement | null) => void; isContentProgrammaticallyChanged: React.RefObject; setIsContentProgrammaticallyChanged: (value: boolean) => void; + isCodeTyping: React.RefObject; + setIsCodeTyping: (value: boolean) => void; importProject: ( fsType: TProjectContext, diff --git a/src/_redux/useAppState.tsx b/src/_redux/useAppState.tsx index 7457b527..c1422971 100644 --- a/src/_redux/useAppState.tsx +++ b/src/_redux/useAppState.tsx @@ -34,6 +34,7 @@ export const useAppState = () => { nodeTree, validNodeTree, needToSelectNodePaths, + needToSelectCode, nodeTreeViewState: { focusedItem: nFocusedItem, expandedItems: nExpandedItems, @@ -116,6 +117,7 @@ export const useAppState = () => { validNodeTree, needToSelectNodePaths, + needToSelectCode, nFocusedItem, nExpandedItems, diff --git a/src/components/main/actionsPanel/nodeTreeView/NodeTreeView.tsx b/src/components/main/actionsPanel/nodeTreeView/NodeTreeView.tsx index 9be075cb..e9871a6e 100644 --- a/src/components/main/actionsPanel/nodeTreeView/NodeTreeView.tsx +++ b/src/components/main/actionsPanel/nodeTreeView/NodeTreeView.tsx @@ -221,12 +221,14 @@ const NodeTreeView = () => { }), [], ); - - const searchConfig = { - canSearch: false, - canSearchByStartingTyping: false, - canRename: false, - }; + const searchConfig = useMemo( + () => ({ + canSearch: false, + canSearchByStartingTyping: false, + canRename: false, + }), + [], + ); return currentFileUid !== "" ? (
{ const { activePanel, currentCommand } = useAppState(); - const {} = useContext(MainContext); const { onAddNode, @@ -20,7 +19,7 @@ export const useCmdk = () => { onTurnInto, onGroup, onUngroup, - } = useNodeActionsHandlers(); + } = useNodeActionHandlers(); useEffect(() => { if (!currentCommand) return; diff --git a/src/components/main/actionsPanel/nodeTreeView/hooks/useNodeActionsHandlers.ts b/src/components/main/actionsPanel/nodeTreeView/hooks/useNodeActionHandlers.ts similarity index 99% rename from src/components/main/actionsPanel/nodeTreeView/hooks/useNodeActionsHandlers.ts rename to src/components/main/actionsPanel/nodeTreeView/hooks/useNodeActionHandlers.ts index 7ba2d666..17558912 100644 --- a/src/components/main/actionsPanel/nodeTreeView/hooks/useNodeActionsHandlers.ts +++ b/src/components/main/actionsPanel/nodeTreeView/hooks/useNodeActionHandlers.ts @@ -8,7 +8,7 @@ import { TNodeUid } from "@_node/types"; import { MainContext } from "@_redux/main"; import { useAppState } from "@_redux/useAppState"; -export const useNodeActionsHandlers = () => { +export const useNodeActionHandlers = () => { const dispatch = useDispatch(); const { nodeTree, @@ -57,7 +57,6 @@ export const useNodeActionsHandlers = () => { }, [nodeTree, focusedItem], ); - const onCut = useCallback(() => { if (selectedItems.length === 0) return; @@ -83,7 +82,6 @@ export const useNodeActionsHandlers = () => { () => setIsContentProgrammaticallyChanged(false), ); }, [selectedItems, nodeTree]); - const onCopy = useCallback(() => { if (selectedItems.length === 0) return; @@ -97,6 +95,8 @@ export const useNodeActionsHandlers = () => { return; } + console.log(callNodeApi); + setIsContentProgrammaticallyChanged(true); callNodeApi( { @@ -109,7 +109,6 @@ export const useNodeActionsHandlers = () => { () => setIsContentProgrammaticallyChanged(false), ); }, [selectedItems, nodeTree]); - const onPaste = useCallback(() => { const focusedNode = validNodeTree[focusedItem]; if (!focusedNode || !focusedNode.data.sourceCodeLocation) { @@ -140,7 +139,6 @@ export const useNodeActionsHandlers = () => { () => setIsContentProgrammaticallyChanged(false), ); }, [validNodeTree, focusedItem]); - const onDelete = useCallback(() => { if (selectedItems.length === 0) return; @@ -166,7 +164,6 @@ export const useNodeActionsHandlers = () => { () => setIsContentProgrammaticallyChanged(false), ); }, [selectedItems, nodeTree]); - const onDuplicate = useCallback(() => { if (selectedItems.length === 0) return; @@ -192,7 +189,6 @@ export const useNodeActionsHandlers = () => { () => setIsContentProgrammaticallyChanged(false), ); }, [selectedItems, nodeTree]); - const onMove = useCallback( ({ selectedUids, @@ -232,7 +228,6 @@ export const useNodeActionsHandlers = () => { }, [nodeTree], ); - const onTurnInto = useCallback( (actionName: string) => { const focusedNode = nodeTree[focusedItem]; @@ -264,7 +259,6 @@ export const useNodeActionsHandlers = () => { }, [nodeTree, focusedItem], ); - const onGroup = useCallback(() => { if (selectedItems.length === 0) return; diff --git a/src/components/main/actionsPanel/nodeTreeView/hooks/useNodeTreeCallback.ts b/src/components/main/actionsPanel/nodeTreeView/hooks/useNodeTreeCallback.ts index f6d3f37e..e887d83b 100644 --- a/src/components/main/actionsPanel/nodeTreeView/hooks/useNodeTreeCallback.ts +++ b/src/components/main/actionsPanel/nodeTreeView/hooks/useNodeTreeCallback.ts @@ -7,7 +7,7 @@ import { TNodeUid } from "@_node/types"; import { MainContext } from "@_redux/main"; import { useAppState } from "@_redux/useAppState"; -import { useNodeActionsHandlers } from "./useNodeActionsHandlers"; +import { useNodeActionHandlers } from "./useNodeActionHandlers"; import { useNodeViewState } from "./useNodeViewState"; export const useNodeTreeCallback = ( @@ -17,7 +17,7 @@ export const useNodeTreeCallback = ( const { validNodeTree } = useAppState(); const { htmlReferenceData } = useContext(MainContext); - const { onMove } = useNodeActionsHandlers(); + const { onMove } = useNodeActionHandlers(); const { cb_focusNode, cb_selectNode, cb_expandNode, cb_collapseNode } = useNodeViewState(); diff --git a/src/components/main/codeView/CodeView.tsx b/src/components/main/codeView/CodeView.tsx index da603c84..6b61e0a7 100644 --- a/src/components/main/codeView/CodeView.tsx +++ b/src/components/main/codeView/CodeView.tsx @@ -19,6 +19,7 @@ import { Editor, loader } from "@monaco-editor/react"; import { useCmdk, useEditor } from "./hooks"; import { CodeViewProps } from "./types"; +import { getNodeUidByCodeSelection } from "./helpers"; loader.config({ monaco }); @@ -35,11 +36,7 @@ export default function CodeView(props: CodeViewProps) { activePanel, showCodeView, } = useAppState(); - const { - isContentProgrammaticallyChanged, - setIsContentProgrammaticallyChanged, - monacoEditorRef, - } = useContext(MainContext); + const { isCodeTyping, monacoEditorRef } = useContext(MainContext); const { handleEditorDidMount, @@ -54,7 +51,6 @@ export default function CodeView(props: CodeViewProps) { setWordWrap, codeSelection, - getNodeUidByCodeSelection, } = useEditor(); useCmdk(); @@ -126,7 +122,7 @@ export default function CodeView(props: CodeViewProps) { // code select -> selectedUids useEffect(() => { - if (!codeSelection) return; + if (!codeSelection || isCodeTyping) return; const file = fileTree[currentFileUid]; if (!file) return; diff --git a/src/components/main/codeView/helpers.ts b/src/components/main/codeView/helpers.ts index 5ef03513..5f15e50b 100644 --- a/src/components/main/codeView/helpers.ts +++ b/src/components/main/codeView/helpers.ts @@ -1,5 +1,9 @@ import { TTheme } from "@_redux/global"; import { getSystemTheme } from "@_services/global"; +import { TCodeSelection } from "./types"; +import { TNodeTreeData, TNodeUid } from "@_node/types"; +import { getSubNodeUidsByBfs } from "@_node/helpers"; +import { RootNodeUid } from "@_constants/main"; export const getLanguageFromExtension = (extension: string) => { if (!!extension) return extension; @@ -18,3 +22,41 @@ export const getCodeViewTheme = (theme: TTheme) => { return "light"; } }; + +export const getNodeUidByCodeSelection = ( + selection: TCodeSelection, + validNodeTree: TNodeTreeData, +): TNodeUid | null => { + let focusedItem: TNodeUid | null = null; + if (selection) { + const uids = getSubNodeUidsByBfs(RootNodeUid, validNodeTree); + uids.reverse(); + for (const uid of uids) { + const node = validNodeTree[uid]; + const sourceCodeLocation = node.data.sourceCodeLocation; + if (!sourceCodeLocation) continue; + + const { + startLine: startLineNumber, + startCol: startColumn, + endCol: endColumn, + endLine: endLineNumber, + } = sourceCodeLocation; + + const containFront = + selection.startLineNumber === startLineNumber + ? selection.startColumn > startColumn + : selection.startLineNumber > startLineNumber; + const containBack = + selection.endLineNumber === endLineNumber + ? selection.endColumn < endColumn + : selection.endLineNumber < endLineNumber; + + if (containFront && containBack) { + focusedItem = uid; + break; + } + } + } + return focusedItem; +}; diff --git a/src/components/main/codeView/hooks/useEditor.ts b/src/components/main/codeView/hooks/useEditor.ts index 904ba9a7..8eb5add8 100644 --- a/src/components/main/codeView/hooks/useEditor.ts +++ b/src/components/main/codeView/hooks/useEditor.ts @@ -8,13 +8,13 @@ import { CodeViewSyncDelay, CodeViewSyncDelay_Long, DefaultTabSize, - RootNodeUid, } from "@_constants/main"; -import { getSubNodeUidsByBfs } from "@_node/helpers"; -import { TNodeTreeData, TNodeUid } from "@_node/types"; import { MainContext } from "@_redux/main"; import { setCodeViewTabSize } from "@_redux/main/codeView"; -import { setCurrentFileContent } from "@_redux/main/nodeTree"; +import { + setCurrentFileContent, + setNeedToSelectCode, +} from "@_redux/main/nodeTree"; import { useAppState } from "@_redux/useAppState"; import { getCodeViewTheme, getLanguageFromExtension } from "../helpers"; @@ -26,9 +26,9 @@ const useEditor = () => { const { monacoEditorRef, setMonacoEditorRef, - isContentProgrammaticallyChanged, setIsContentProgrammaticallyChanged, + setIsCodeTyping, onUndo, onRedo, @@ -84,46 +84,6 @@ const useEditor = () => { const _selection = monacoEditor?.getSelection(); _setCodeSelection(_selection ? _selection : null); }, []); - const getNodeUidByCodeSelection = useCallback( - ( - selection: TCodeSelection, - validNodeTree: TNodeTreeData, - ): TNodeUid | null => { - let focusedItem: TNodeUid | null = null; - if (selection) { - const uids = getSubNodeUidsByBfs(RootNodeUid, validNodeTree); - uids.reverse(); - for (const uid of uids) { - const node = validNodeTree[uid]; - const sourceCodeLocation = node.data.sourceCodeLocation; - if (!sourceCodeLocation) continue; - - const { - startLine: startLineNumber, - startCol: startColumn, - endCol: endColumn, - endLine: endLineNumber, - } = sourceCodeLocation; - - const containFront = - selection.startLineNumber === startLineNumber - ? selection.startColumn > startColumn - : selection.startLineNumber > startLineNumber; - const containBack = - selection.endLineNumber === endLineNumber - ? selection.endColumn < endColumn - : selection.endLineNumber < endLineNumber; - - if (containFront && containBack) { - focusedItem = uid; - break; - } - } - } - return focusedItem; - }, - [], - ); // handlerEditorDidMount const handleEditorDidMount = useCallback( @@ -160,15 +120,22 @@ const useEditor = () => { const handleOnChange = useCallback((value: string | undefined) => { if (value === undefined) return; + setIsCodeTyping(true); + if (isContentProgrammaticallyChanged.current) { debouncedOnChange(value); } else { longDebouncedOnChange(value); } }, []); - const onChange = useCallback((value: string) => { - dispatch(setCurrentFileContent(value)); - }, []); + const onChange = useCallback( + (value: string) => { + dispatch(setCurrentFileContent(value)); + dispatch(setNeedToSelectCode(codeSelection)); + setIsCodeTyping(false); + }, + [codeSelection], + ); const debouncedOnChange = useCallback( debounce((value) => { onChange(value); @@ -207,7 +174,6 @@ const useEditor = () => { setWordWrap, codeSelection, - getNodeUidByCodeSelection, }; }; diff --git a/src/components/main/codeView/index.ts b/src/components/main/codeView/index.ts index 13b46c7b..41f79a78 100644 --- a/src/components/main/codeView/index.ts +++ b/src/components/main/codeView/index.ts @@ -3,3 +3,4 @@ import CodeView from "./CodeView"; export default CodeView; export * from "./types"; +export * from "./helpers"; diff --git a/src/pages/main/MainPage.tsx b/src/pages/main/MainPage.tsx index 5cdee720..c2018a9e 100644 --- a/src/pages/main/MainPage.tsx +++ b/src/pages/main/MainPage.tsx @@ -127,6 +127,8 @@ export default function MainPage() { setIframeRefRef, isContentProgrammaticallyChanged, setIsContentProgrammaticallyChanged, + isCodeTyping, + setIsCodeTyping, } = useReferneces(); const { validMenuItemCount, hoveredMenuItemDescription } = useCmdkModal(); const { @@ -188,6 +190,8 @@ export default function MainPage() { setIframeRefRef, isContentProgrammaticallyChanged, setIsContentProgrammaticallyChanged, + isCodeTyping, + setIsCodeTyping, importProject, onUndo, diff --git a/src/pages/main/hooks/useReferences.ts b/src/pages/main/hooks/useReferences.ts index be9d365e..a1433be6 100644 --- a/src/pages/main/hooks/useReferences.ts +++ b/src/pages/main/hooks/useReferences.ts @@ -1,22 +1,27 @@ -import { useRef } from "react"; +import { useCallback, useRef } from "react"; import { editor } from "monaco-editor"; export const useReferneces = () => { const monacoEditorRef = useRef(null); - const setMonacoEditorRef = ( - editorInstance: editor.IStandaloneCodeEditor | null, - ) => { - monacoEditorRef.current = editorInstance; - }; + const setMonacoEditorRef = useCallback( + (editorInstance: editor.IStandaloneCodeEditor | null) => { + monacoEditorRef.current = editorInstance; + }, + [], + ); const iframeRefRef = useRef(null); - const setIframeRefRef = (iframeRef: HTMLIFrameElement | null) => { + const setIframeRefRef = useCallback((iframeRef: HTMLIFrameElement | null) => { iframeRefRef.current = iframeRef; - }; - const isContentProgrammaticallyChanged = useRef(false); - const setIsContentProgrammaticallyChanged = (value: boolean) => { + }, []); + const isContentProgrammaticallyChanged = useRef(false); + const setIsContentProgrammaticallyChanged = useCallback((value: boolean) => { isContentProgrammaticallyChanged.current = value; - }; + }, []); + const isCodeTyping = useRef(false); + const setIsCodeTyping = useCallback((value: boolean) => { + isCodeTyping.current = value; + }, []); return { monacoEditorRef, @@ -25,5 +30,7 @@ export const useReferneces = () => { setIframeRefRef, isContentProgrammaticallyChanged, setIsContentProgrammaticallyChanged, + isCodeTyping, + setIsCodeTyping, }; }; diff --git a/src/pages/main/processor/hooks/useNodeTreeEvent.ts b/src/pages/main/processor/hooks/useNodeTreeEvent.ts index b6dcca1c..eb6fc33b 100644 --- a/src/pages/main/processor/hooks/useNodeTreeEvent.ts +++ b/src/pages/main/processor/hooks/useNodeTreeEvent.ts @@ -26,6 +26,8 @@ import { focusNodeTreeNode, selectNodeTreeNodes, setExpandedNodeTreeNodes, + setNeedToSelectCode, + setNeedToSelectNodePaths, setNeedToSelectNodeUids, setNodeTree, setSelectedNodeUids, @@ -41,6 +43,7 @@ import { getValidNodeTree, markChangedFolders, } from "../helpers"; +import { getNodeUidByCodeSelection } from "@_components/main/codeView"; export const useNodeTreeEvent = () => { const dispatch = useDispatch(); @@ -57,6 +60,7 @@ export const useNodeTreeEvent = () => { validNodeTree, needToSelectNodePaths, + needToSelectCode, nExpandedItems, syncConfigs, @@ -255,18 +259,40 @@ export const useNodeTreeEvent = () => { ); if (!isSelectedNodeUidsChanged.current) { - // this means we called `callNodeApi` and we need to select predicted `needToSelectNodeUids` - // in the case, `callNodeApi -> setCurrentFileContent` and `setNeedToSelectNodeUids` dispatch actions are considered as an one event in the node-event-history. - const needToSelectNodeUids = getNodeUidsFromPaths( - _validNodeTree, - needToSelectNodePaths, - ); - dispatch(setNeedToSelectNodeUids(needToSelectNodeUids)); + // this change is from 'node actions' or 'typing in code-view' + let _selectedNodeUids: TNodeUid[] = []; + + if (needToSelectCode) { + LogAllow && console.log("it's a rnbw-change from code-view"); + // it's a typing change in code-view and we need to select currently `cursored node` in code-view. + // in the case, `callNodeApi -> setCurrentFileContent` and `setNeedToSelectNodeUids` dispatch actions are considered as an one event in the node-event-history. + const focusedNodeUid = getNodeUidByCodeSelection( + needToSelectCode, + _validNodeTree, + ); + focusedNodeUid && + _selectedNodeUids.push(focusedNodeUid) && + dispatch(setNeedToSelectNodeUids([focusedNodeUid])); + dispatch(setNeedToSelectCode(null)); + } + + if (needToSelectNodePaths) { + LogAllow && console.log("it's a rnbw-change from node-actions"); + // this means we called `callNodeApi` and we need to select predicted `needToSelectNodeUids` + // in the case, `callNodeApi -> setCurrentFileContent` and `setNeedToSelectNodeUids` dispatch actions are considered as an one event in the node-event-history. + const needToSelectNodeUids = getNodeUidsFromPaths( + _validNodeTree, + needToSelectNodePaths, + ); + _selectedNodeUids.push(...needToSelectNodeUids); + dispatch(setNeedToSelectNodeUids(needToSelectNodeUids)); + dispatch(setNeedToSelectNodePaths(null)); + } // remark selected elements on stage-view // it is removed through dom-diff // this part is for when the selectedNodeUids is not changed cuz of the same code-format - markSelectedElements(iframeRefRef.current, needToSelectNodeUids); + markSelectedElements(iframeRefRef.current, _selectedNodeUids); } } From c531a170f7498bcc2b3ad398ccecfa4e9b1ba687 Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 14 Dec 2023 14:41:30 +0800 Subject: [PATCH 2/6] import bug fix --- src/_node/apis.ts | 3 ++- .../actionsPanel/nodeTreeView/hooks/useNodeActionHandlers.ts | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/_node/apis.ts b/src/_node/apis.ts index 3b20c020..7a2c119f 100644 --- a/src/_node/apis.ts +++ b/src/_node/apis.ts @@ -1,4 +1,5 @@ -import { doFileActions, doNodeActions } from "./"; +import { doNodeActions } from "./node"; +import { doFileActions } from "./file"; export const callNodeApi = doNodeActions; export const callFileApi = doFileActions; diff --git a/src/components/main/actionsPanel/nodeTreeView/hooks/useNodeActionHandlers.ts b/src/components/main/actionsPanel/nodeTreeView/hooks/useNodeActionHandlers.ts index 17558912..c40c6ee2 100644 --- a/src/components/main/actionsPanel/nodeTreeView/hooks/useNodeActionHandlers.ts +++ b/src/components/main/actionsPanel/nodeTreeView/hooks/useNodeActionHandlers.ts @@ -3,10 +3,11 @@ import { useCallback, useContext } from "react"; import { useDispatch } from "react-redux"; import { LogAllow } from "@_constants/global"; -import { callNodeApi } from "@_node/apis"; import { TNodeUid } from "@_node/types"; import { MainContext } from "@_redux/main"; import { useAppState } from "@_redux/useAppState"; +import { doNodeActions } from "@_node/node"; +import { callNodeApi } from "@_node/apis"; export const useNodeActionHandlers = () => { const dispatch = useDispatch(); From 762ae4ca3086199c30f0ee7b27d09f78d5a6ad2d Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 14 Dec 2023 15:08:50 +0800 Subject: [PATCH 3/6] typo fixes --- .../nodeTreeView/hooks/useNodeActionHandlers.ts | 2 -- .../actionsPanel/workspaceTreeView/WorkspaceTreeView.tsx | 6 +----- src/components/main/codeView/CodeView.tsx | 2 +- src/pages/main/processor/hooks/useNodeTreeEvent.ts | 9 ++++----- 4 files changed, 6 insertions(+), 13 deletions(-) diff --git a/src/components/main/actionsPanel/nodeTreeView/hooks/useNodeActionHandlers.ts b/src/components/main/actionsPanel/nodeTreeView/hooks/useNodeActionHandlers.ts index c40c6ee2..580d3980 100644 --- a/src/components/main/actionsPanel/nodeTreeView/hooks/useNodeActionHandlers.ts +++ b/src/components/main/actionsPanel/nodeTreeView/hooks/useNodeActionHandlers.ts @@ -96,8 +96,6 @@ export const useNodeActionHandlers = () => { return; } - console.log(callNodeApi); - setIsContentProgrammaticallyChanged(true); callNodeApi( { diff --git a/src/components/main/actionsPanel/workspaceTreeView/WorkspaceTreeView.tsx b/src/components/main/actionsPanel/workspaceTreeView/WorkspaceTreeView.tsx index aa54e4b7..5f98eea9 100644 --- a/src/components/main/actionsPanel/workspaceTreeView/WorkspaceTreeView.tsx +++ b/src/components/main/actionsPanel/workspaceTreeView/WorkspaceTreeView.tsx @@ -197,11 +197,7 @@ export default function WorkspaceTreeView() { // open default initial html file useEffect(() => { if (initialFileUidToOpen !== "" && fileTree[initialFileUidToOpen]) { - addRunningActions([ - "fileTreeView-focus", - "fileTreeView-select", - "fileTreeView-read", - ]); + addRunningActions(["fileTreeView-read"]); cb_focusNode(initialFileUidToOpen); cb_selectNode([initialFileUidToOpen]); diff --git a/src/components/main/codeView/CodeView.tsx b/src/components/main/codeView/CodeView.tsx index 6b61e0a7..03ed0f53 100644 --- a/src/components/main/codeView/CodeView.tsx +++ b/src/components/main/codeView/CodeView.tsx @@ -122,7 +122,7 @@ export default function CodeView(props: CodeViewProps) { // code select -> selectedUids useEffect(() => { - if (!codeSelection || isCodeTyping) return; + if (!codeSelection || isCodeTyping.current) return; const file = fileTree[currentFileUid]; if (!file) return; diff --git a/src/pages/main/processor/hooks/useNodeTreeEvent.ts b/src/pages/main/processor/hooks/useNodeTreeEvent.ts index eb6fc33b..230176a7 100644 --- a/src/pages/main/processor/hooks/useNodeTreeEvent.ts +++ b/src/pages/main/processor/hooks/useNodeTreeEvent.ts @@ -261,18 +261,17 @@ export const useNodeTreeEvent = () => { if (!isSelectedNodeUidsChanged.current) { // this change is from 'node actions' or 'typing in code-view' let _selectedNodeUids: TNodeUid[] = []; - if (needToSelectCode) { LogAllow && console.log("it's a rnbw-change from code-view"); // it's a typing change in code-view and we need to select currently `cursored node` in code-view. // in the case, `callNodeApi -> setCurrentFileContent` and `setNeedToSelectNodeUids` dispatch actions are considered as an one event in the node-event-history. - const focusedNodeUid = getNodeUidByCodeSelection( + const needToSelectNodeUid = getNodeUidByCodeSelection( needToSelectCode, _validNodeTree, ); - focusedNodeUid && - _selectedNodeUids.push(focusedNodeUid) && - dispatch(setNeedToSelectNodeUids([focusedNodeUid])); + needToSelectNodeUid && + _selectedNodeUids.push(needToSelectNodeUid) && + dispatch(setNeedToSelectNodeUids([needToSelectNodeUid])); dispatch(setNeedToSelectCode(null)); } From f8ebed8c02f55cd6419fc2a1c9257de475d9c94d Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 14 Dec 2023 15:09:22 +0800 Subject: [PATCH 4/6] catch keyboard cursor change event in code-view fix callback dependency --- .../main/codeView/hooks/useEditor.ts | 46 +++++++++++++------ 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/src/components/main/codeView/hooks/useEditor.ts b/src/components/main/codeView/hooks/useEditor.ts index 8eb5add8..d728ae26 100644 --- a/src/components/main/codeView/hooks/useEditor.ts +++ b/src/components/main/codeView/hooks/useEditor.ts @@ -110,28 +110,30 @@ const useEditor = () => { })), ); - editor.onDidChangeCursorPosition( - (event) => event.source === "mouse" && setCodeSelection(), - ); + editor.onDidChangeCursorPosition((event) => { + (event.source === "mouse" || event.source === "keyboard") && + setCodeSelection(); + }); }, [setCodeSelection], ); - // handleOnChange - const handleOnChange = useCallback((value: string | undefined) => { - if (value === undefined) return; - - setIsCodeTyping(true); - if (isContentProgrammaticallyChanged.current) { - debouncedOnChange(value); - } else { - longDebouncedOnChange(value); - } - }, []); + // handleOnChange const onChange = useCallback( (value: string) => { dispatch(setCurrentFileContent(value)); - dispatch(setNeedToSelectCode(codeSelection)); + dispatch( + setNeedToSelectCode( + codeSelection + ? { + startLineNumber: codeSelection.startLineNumber, + startColumn: codeSelection.startColumn, + endLineNumber: codeSelection.endLineNumber, + endColumn: codeSelection.endColumn, + } + : null, + ), + ); setIsCodeTyping(false); }, [codeSelection], @@ -147,6 +149,20 @@ const useEditor = () => { debounce(onChange, CodeViewSyncDelay_Long), [onChange], ); + const handleOnChange = useCallback( + (value: string | undefined) => { + if (value === undefined) return; + + setIsCodeTyping(true); + + if (isContentProgrammaticallyChanged.current) { + debouncedOnChange(value); + } else { + longDebouncedOnChange(value); + } + }, + [debouncedOnChange, longDebouncedOnChange], + ); // undo/redo const [undoRedoToggle, setUndoRedoToggle] = useState<{ From e01a06876e7c530a87ed6722b4b2ded9e66101ae Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 14 Dec 2023 15:14:05 +0800 Subject: [PATCH 5/6] use codeSelection reference instead of state in debounced function --- .../main/codeView/hooks/useEditor.ts | 48 +++++++++++-------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/src/components/main/codeView/hooks/useEditor.ts b/src/components/main/codeView/hooks/useEditor.ts index d728ae26..a0eea15f 100644 --- a/src/components/main/codeView/hooks/useEditor.ts +++ b/src/components/main/codeView/hooks/useEditor.ts @@ -1,4 +1,11 @@ -import { useCallback, useContext, useEffect, useMemo, useState } from "react"; +import { + useCallback, + useContext, + useEffect, + useMemo, + useRef, + useState, +} from "react"; import { debounce } from "lodash"; import { editor, KeyCode, KeyMod } from "monaco-editor"; @@ -79,6 +86,10 @@ const useEditor = () => { const [codeSelection, _setCodeSelection] = useState( null, ); + const codeSelectionRef = useRef(null); + useEffect(() => { + codeSelectionRef.current = codeSelection; + }, [codeSelection]); const setCodeSelection = useCallback(() => { const monacoEditor = monacoEditorRef.current; const _selection = monacoEditor?.getSelection(); @@ -119,25 +130,22 @@ const useEditor = () => { ); // handleOnChange - const onChange = useCallback( - (value: string) => { - dispatch(setCurrentFileContent(value)); - dispatch( - setNeedToSelectCode( - codeSelection - ? { - startLineNumber: codeSelection.startLineNumber, - startColumn: codeSelection.startColumn, - endLineNumber: codeSelection.endLineNumber, - endColumn: codeSelection.endColumn, - } - : null, - ), - ); - setIsCodeTyping(false); - }, - [codeSelection], - ); + const onChange = useCallback((value: string) => { + dispatch(setCurrentFileContent(value)); + dispatch( + setNeedToSelectCode( + codeSelectionRef.current + ? { + startLineNumber: codeSelectionRef.current.startLineNumber, + startColumn: codeSelectionRef.current.startColumn, + endLineNumber: codeSelectionRef.current.endLineNumber, + endColumn: codeSelectionRef.current.endColumn, + } + : null, + ), + ); + setIsCodeTyping(false); + }, []); const debouncedOnChange = useCallback( debounce((value) => { onChange(value); From 93d1831eed382a9f2f205d43bae4370a7e1a1471 Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 14 Dec 2023 17:31:24 +0800 Subject: [PATCH 6/6] keep treeview config as constant variable --- .../nodeTreeView/NodeTreeView.tsx | 29 +++++++------------ .../actionsPanel/nodeTreeView/constants.ts | 1 + 2 files changed, 12 insertions(+), 18 deletions(-) create mode 100644 src/components/main/actionsPanel/nodeTreeView/constants.ts diff --git a/src/components/main/actionsPanel/nodeTreeView/NodeTreeView.tsx b/src/components/main/actionsPanel/nodeTreeView/NodeTreeView.tsx index e9871a6e..3e7dc6f1 100644 --- a/src/components/main/actionsPanel/nodeTreeView/NodeTreeView.tsx +++ b/src/components/main/actionsPanel/nodeTreeView/NodeTreeView.tsx @@ -42,6 +42,17 @@ import { ItemTitle } from "./nodeTreeComponents/ItemTitle"; import { NodeIcon } from "./nodeTreeComponents/NodeIcon"; const AutoExpandDelayOnDnD = 1 * 1000; +const dragAndDropConfig = { + canDragAndDrop: true, + canDropOnFolder: true, + canDropOnNonFolder: true, + canReorderItems: true, +}; +const searchConfig = { + canSearch: false, + canSearchByStartingTyping: false, + canRename: false, +}; const NodeTreeView = () => { const dispatch = useDispatch(); @@ -212,24 +223,6 @@ const NodeTreeView = () => { const callbacks = useNodeTreeCallback(focusedItemRef.current, isDragging); - const dragAndDropConfig = useMemo( - () => ({ - canDragAndDrop: true, - canDropOnFolder: true, - canDropOnNonFolder: true, - canReorderItems: true, - }), - [], - ); - const searchConfig = useMemo( - () => ({ - canSearch: false, - canSearchByStartingTyping: false, - canRename: false, - }), - [], - ); - return currentFileUid !== "" ? (