diff --git a/src/_node/file/FileSystemApis.ts b/src/_node/file/FileSystemApis.ts index c4ba1d65..9f328a94 100644 --- a/src/_node/file/FileSystemApis.ts +++ b/src/_node/file/FileSystemApis.ts @@ -1,3 +1,5 @@ +import { FileSystemFileHandle } from "file-system-access"; + import { verifyFileHandlerPermission } from "@_services/main"; import { @@ -10,13 +12,12 @@ import { import { _createIDBDirectory, _getIDBDirectoryOrFileStat, + _path, _readIDBDirectory, _readIDBFile, _removeIDBDirectoryOrFile, _writeIDBFile, - _path, } from "./nohostApis"; -import { FileSystemFileHandle } from "file-system-access"; // true: success, false: fail const createLocalSingleDirectoryOrFile = async ({ diff --git a/src/_node/file/actions.ts b/src/_node/file/actions.ts index 56eafc0f..b5e6f4c8 100644 --- a/src/_node/file/actions.ts +++ b/src/_node/file/actions.ts @@ -1,41 +1,30 @@ +import { Dispatch } from "react"; + import { LogAllow } from "@_constants/global"; +import { TProjectContext } from "@_redux/main/fileTree"; +import { setClipboardData, TClipboardData } from "@_redux/main/processor"; +import { AnyAction } from "@reduxjs/toolkit"; import { TFileApiPayload, TFileHandlerCollection, - TFileNodeData, TFileNodeTreeData, - TNode, TNodeTreeData, TNodeUid, - moveIDBFF, - moveLocalFF, } from "../"; -import { - TFileAction, - TProjectContext, - setCurrentFileUid, - setFileAction, - updateFileTreeViewState, -} from "@_redux/main/fileTree"; import { FileSystemApis } from "./FileSystemApis"; -import { TClipboardData, setClipboardData } from "@_redux/main/processor"; -import { AnyAction } from "@reduxjs/toolkit"; -import { Dispatch } from "react"; -import { generateNewNameMoveNode } from "@_components/main/actionsPanel/workspaceTreeView/helpers"; -import { verifyFileHandlerPermission } from "@_services/main"; const create = () => {}; const remove = async ({ projectContext, - uids, fileTree, fileHandlers, + uids, }: { projectContext: TProjectContext; - uids: TNodeUid[]; fileTree: TFileNodeTreeData; fileHandlers?: TFileHandlerCollection; + uids: TNodeUid[]; }): Promise => { return new Promise((resolve, reject) => { try { @@ -59,21 +48,22 @@ const remove = async ({ const move = async ({ projectContext, + fileTree, fileHandlers, uids, clipboardData, - fileTree, targetNode, }: { projectContext: TProjectContext; - fileHandlers: any; - uids: string[]; + fileHandlers?: TFileHandlerCollection; + uids: TNodeUid[]; clipboardData: TClipboardData | null; fileTree: TFileNodeTreeData; targetNode: any; -}) => { +}): Promise => { return new Promise((resolve, reject) => { - uids.map(async (uid) => { + resolve(true); + /* uids.map(async (uid) => { const node = fileTree[uid]; if (node === undefined) { return false; @@ -136,10 +126,9 @@ const move = async ({ } catch (err) { reject(err); } - }); + }); */ }); }; - const cut = ({ dispatch, uids, @@ -150,7 +139,7 @@ const cut = ({ dispatch: Dispatch; uids: TNodeUid[]; fileTree: TFileNodeTreeData; - currentFileUid: string; + currentFileUid: TNodeUid; nodeTree: TNodeTreeData; }) => { dispatch( @@ -165,7 +154,6 @@ const cut = ({ }), ); }; - const copy = ({ dispatch, uids, @@ -191,7 +179,6 @@ const copy = ({ }), ); }; - const rename = ({ dispatch, projectContext, @@ -206,9 +193,10 @@ const rename = ({ fileTree: TFileNodeTreeData; uids: TNodeUid[]; newName: string; -}) => { +}): Promise => { return new Promise((resolve, reject) => { - const renameUid = uids[0]; + resolve(true); + /* const renameUid = uids[0]; const node = fileTree[renameUid]; if (node === undefined) { return false; @@ -267,16 +255,9 @@ const rename = ({ } })(); - /* const action: TFileAction = { - type: "rename", - param1: { currentFileUid: renameUid, parentUid: parentUid }, - param2: { orgName: _orgName, newName: _newName }, - }; - dispatch(setFileAction(action)); */ - // update redux dispatch(setCurrentFileUid(newUid)); - dispatch(updateFileTreeViewState({ convertedUids: [[renameUid, newUid]] })); + dispatch(updateFileTreeViewState({ convertedUids: [[renameUid, newUid]] })); */ }); }; @@ -314,37 +295,37 @@ export const doFileActions = async ( }); break; case "cut": - cut({ + /* cut({ dispatch, uids, fileTree, currentFileUid, nodeTree, - }); + }); */ break; case "copy": - copy({ dispatch, uids, fileTree, currentFileUid, nodeTree }); + // copy({ dispatch, uids, fileTree, currentFileUid, nodeTree }); break; case "move": - allDone = await move({ + /* allDone = await move({ projectContext, fileHandlers, uids, clipboardData, fileTree, targetNode, - }); + }); */ break; case "rename": - rename({ + /* rename({ dispatch, projectContext, fileHandlers, fileTree, uids, newName, - }); + }); */ break; default: break; diff --git a/src/_node/file/apis.ts b/src/_node/file/apis.ts index 626069c0..85716880 100644 --- a/src/_node/file/apis.ts +++ b/src/_node/file/apis.ts @@ -1,5 +1,6 @@ import { Buffer } from "buffer"; import FileSaver from "file-saver"; +import { FileSystemFileHandle } from "file-system-access"; import JSZip from "jszip"; import { LogAllow } from "@_constants/global"; @@ -9,17 +10,12 @@ import { StagePreviewPathPrefix, } from "@_constants/main"; import { TOsType } from "@_redux/global"; -// @ts-ignore -import htmlRefElements from "@_ref/rfrncs/HTML Elements.csv"; import { SystemDirectories } from "@_ref/SystemDirectories"; import { verifyFileHandlerPermission } from "@_services/main"; -import { - THtmlElementsReference, - THtmlElementsReferenceData, -} from "@_types/main"; import { fileHandlers, + getIndexHtmlContent, getSubNodeUidsByBfs, TFileHandlerCollection, TFileNode, @@ -31,18 +27,16 @@ import { TNodeUid, } from "../"; import { getInitialFileUidToOpen, sortFilesByASC } from "./helpers"; -import { TFileHandlerInfo, TFileHandlerInfoObj, TZipFileInfo } from "./types"; -import { FileSystemFileHandle } from "file-system-access"; - import { _createIDBDirectory, _getIDBDirectoryOrFileStat, + _path, _readIDBDirectory, _readIDBFile, _removeIDBDirectoryOrFile, _writeIDBFile, - _path, } from "./nohostApis"; +import { TFileHandlerInfo, TFileHandlerInfoObj, TZipFileInfo } from "./types"; export const initIDBProject = async (projectPath: string): Promise => { return new Promise(async (resolve, reject) => { @@ -50,7 +44,7 @@ export const initIDBProject = async (projectPath: string): Promise => { try { await _removeIDBDirectoryOrFile(projectPath); } catch (err) { - LogAllow && console.error("error while remove IDB project", err); + LogAllow && console.error("error while removing IDB project", err); } // create a new project @@ -62,24 +56,6 @@ export const initIDBProject = async (projectPath: string): Promise => { } }); }; -export const getIndexHtmlContent = () => { - const htmlElementsReferenceData: THtmlElementsReferenceData = {}; - htmlRefElements.map((htmlRefElement: THtmlElementsReference) => { - const pureTag = - htmlRefElement["Name"] === "Comment" - ? "comment" - : htmlRefElement["Tag"]?.slice(1, htmlRefElement["Tag"].length - 1); - htmlElementsReferenceData[pureTag] = htmlRefElement; - }); - - const doctype = "\n"; - const html = htmlElementsReferenceData["html"].Content - ? `\n` + htmlElementsReferenceData["html"].Content + `\n` - : `Untitled

Heading 1

`; - const indexHtmlContent = doctype + html; - return indexHtmlContent; -}; - export const createIDBProject = async (projectPath: string): Promise => { return new Promise(async (resolve, reject) => { try { @@ -93,11 +69,12 @@ export const createIDBProject = async (projectPath: string): Promise => { resolve(); } catch (err) { - LogAllow && console.error("error while create IDB project", err); + LogAllow && console.error("error while creating IDB project", err); reject(err); } }); }; + export const loadIDBProject = async ( projectPath: string, isReload: boolean = false, @@ -141,40 +118,41 @@ export const loadIDBProject = async ( if (entry.startsWith(StagePreviewPathPrefix) || entry[0] === ".") return; - // build c_handler - const c_uid = _path.join(p_uid, entry) as string; - const c_path = _path.join(p_path, entry) as string; - - const stats = await _getIDBDirectoryOrFileStat(c_path); - const c_kind = stats.type === "DIRECTORY" ? "directory" : "file"; - - const nameArr = entry.split("."); - const c_ext = nameArr.length > 1 ? nameArr.pop() : undefined; - const c_name = nameArr.join("."); - - const c_content = - c_kind === "directory" ? undefined : await _readIDBFile(c_path); - - const c_handlerInfo: TFileHandlerInfo = { - uid: c_uid, - parentUid: p_uid, - children: [], - - path: c_path, - kind: c_kind, - name: c_kind === "directory" ? entry : c_name, - - ext: c_ext, - content: c_content, - }; - - // update handlerObj & dirHandlers - handlerObj[c_uid] = c_handlerInfo; - handlerObj[p_uid].children.push(c_uid); - c_kind === "directory" && dirHandlers.push(c_handlerInfo); - - // remove c_uid from deletedUids array - delete deletedUidsObj[c_uid]; + try { + // build c_handler + const c_uid = _path.join(p_uid, entry) as string; + const c_path = _path.join(p_path, entry) as string; + const stats = await _getIDBDirectoryOrFileStat(c_path); + const c_kind = stats.type === "DIRECTORY" ? "directory" : "file"; + + const nameArr = entry.split("."); + const c_ext = nameArr.length > 1 ? nameArr.pop() : undefined; + const c_name = nameArr.join("."); + + const c_content = + c_kind === "directory" ? undefined : await _readIDBFile(c_path); + + const c_handlerInfo: TFileHandlerInfo = { + uid: c_uid, + parentUid: p_uid, + children: [], + + path: c_path, + kind: c_kind, + name: c_kind === "directory" ? entry : c_name, + + ext: c_ext, + content: c_content, + }; + + // update handlerObj & dirHandlers + handlerObj[c_uid] = c_handlerInfo; + handlerObj[p_uid].children.push(c_uid); + c_kind === "directory" && dirHandlers.push(c_handlerInfo); + + // remove c_uid from deletedUids array + delete deletedUidsObj[c_uid]; + } catch (err) {} }), ); } @@ -406,10 +384,7 @@ export const buildNohostIDB = async ( deletedPaths.map(async (path) => { try { await _removeIDBDirectoryOrFile(path); - } catch (err) { - LogAllow && - console.error("error while deleting in buildNohostIDB API", err); - } + } catch (err) {} }), ); await Promise.all( @@ -418,23 +393,11 @@ export const buildNohostIDB = async ( if (kind === "directory") { try { await _createIDBDirectory(path); - } catch (err) { - LogAllow && - console.error( - "error whil creating a directory in buildNohostIDB API", - err, - ); - } + } catch (err) {} } else { try { await _writeIDBFile(path, content as Uint8Array); - } catch (err) { - LogAllow && - console.error( - "error while creating a file in buildNohostIDB API", - err, - ); - } + } catch (err) {} } }), ); @@ -446,6 +409,7 @@ export const buildNohostIDB = async ( } }); }; + export const downloadIDBProject = async ( projectPath: string, ): Promise => { diff --git a/src/_node/file/helpers.ts b/src/_node/file/helpers.ts index cca7ed63..1b2c815f 100644 --- a/src/_node/file/helpers.ts +++ b/src/_node/file/helpers.ts @@ -1,20 +1,22 @@ import { FileChangeAlertMessage, RootNodeUid } from "@_constants/main"; +// @ts-ignore +import htmlRefElements from "@_ref/rfrncs/HTML Elements.csv"; +import { + THtmlElementsReference, + THtmlElementsReferenceData, +} from "@_types/main"; import { - TFileHandlerInfoObj, - TFileNodeData, - TFileNodeTreeData, - TNodeUid, _getIDBDirectoryOrFileStat, _path, _readIDBFile, _removeIDBDirectoryOrFile, _writeIDBFile, + TFileHandlerInfoObj, + TFileNodeData, + TFileNodeTreeData, + TNodeUid, } from "../"; -import { - copyDirectory, - moveDirectory, -} from "@_components/main/actionsPanel/workspaceTreeView/helpers"; export const sortFilesByASC = (handlerObj: TFileHandlerInfoObj) => { // sort by ASC directory/file @@ -93,172 +95,20 @@ export const getNormalizedPath = ( const normalizedPath = _path.normalize(path); return { isAbsolutePath, normalizedPath }; }; +export const getIndexHtmlContent = () => { + const htmlElementsReferenceData: THtmlElementsReferenceData = {}; + htmlRefElements.map((htmlRefElement: THtmlElementsReference) => { + const pureTag = + htmlRefElement["Name"] === "Comment" + ? "comment" + : htmlRefElement["Tag"]?.slice(1, htmlRefElement["Tag"].length - 1); + htmlElementsReferenceData[pureTag] = htmlRefElement; + }); -export const moveFile = async ( - handler: FileSystemHandle, - parentHandler: FileSystemDirectoryHandle, - targetHandler: FileSystemDirectoryHandle, - newName: string, - copy: boolean, - showWarning?: boolean, - // addMessage?: (message: TToast) => void, -) => { - // validate if the new name exists - console.log("move file"); - - let exists = true; - try { - await targetHandler.getFileHandle(newName, { - create: false, - }); - exists = true; - } catch (err) { - exists = false; - } - - if (exists) { - showWarning && alert("File with the same name already exists."); - return; - } - - // create a new file with the new name and write the content - try { - const newFile = await targetHandler.getFileHandle(newName, { - create: true, - }); - - const content = await (handler as FileSystemFileHandle).getFile(); - - const writableStream = await newFile.createWritable(); - await writableStream.write(content); - await writableStream.close(); - - // handle copy(optional) - !copy && - (await parentHandler.removeEntry(handler.name, { recursive: true })); - } catch (err) { - throw new Error("error"); - } -}; -export const moveLocalFF = async ( - handler: FileSystemHandle, - parentHandler: FileSystemDirectoryHandle, - targetHandler: FileSystemDirectoryHandle, - newName: string, - copy: boolean = false, - showWarning: boolean = false, -) => { - if (handler.kind === "directory") { - // validate if the new name exists - let exists = true; - try { - await targetHandler.getDirectoryHandle(newName, { create: false }); - exists = true; - } catch (err) { - exists = false; - } - if (exists) { - // showWarning && - // addMessage({ - // type: "error", - // content: "Folder with the same name already exists.", - // }); - return; - } - - // move nested handler-dir to targetHandler with the newName - copy (optional) - try { - const newHandler = await targetHandler.getDirectoryHandle(newName, { - create: true, - }); - await copyDirectory( - handler as FileSystemDirectoryHandle, - newHandler, - copy, - ); - } catch (err) { - throw new Error("error"); - } - } else { - await moveFile( - handler, - parentHandler, - targetHandler, - newName, - copy, - // showWarning, - // addMessage, - ); - } -}; - -export const moveIDBFF = async ( - nodeData: TFileNodeData, - targetNodeData: TFileNodeData, - newName: string, - copy: boolean = false, -) => { - if (nodeData.kind === "directory") { - // validate if the new name exists - let exists = true; - try { - await _getIDBDirectoryOrFileStat(`${targetNodeData.path}/${newName}`); - exists = true; - } catch (err) { - exists = false; - } - if (exists) { - // showWarning && - // addMessage({ - // type: "error", - // content: "Folder with the same name already exists.", - // }); - return; - } - - // move nested handler-dir to targetHandler with the newName - copy (optional) - try { - const dirs = [ - { - orgPath: nodeData.path, - newPath: `${targetNodeData.path}/${newName}`, - }, - ]; - for (const { orgPath, newPath } of dirs) { - await moveDirectory(orgPath, newPath, copy, nodeData); - } - } catch (err) { - throw "error"; - } - } else { - // validate if the new name exists - let exists = true; - try { - await _getIDBDirectoryOrFileStat(`${targetNodeData.path}/${newName}`); - exists = true; - } catch (err) { - exists = false; - } - if (exists) { - // showWarning && - // addMessage({ - // type: "error", - // content: "File with the same name already exists.", - // }); - return; - } - - // create a new file with the new name and write the content - try { - await _writeIDBFile( - `${targetNodeData.path}/${newName}`, - await _readIDBFile(nodeData.path), - ); - - // handle copy(optional) - !copy && (await _removeIDBDirectoryOrFile(nodeData.path)); - } catch (err) { - throw "error"; - } - } + const doctype = "\n"; + const html = htmlElementsReferenceData["html"].Content + ? `\n` + htmlElementsReferenceData["html"].Content + `\n` + : `Untitled

Heading 1

`; + const indexHtmlContent = doctype + html; + return indexHtmlContent; }; diff --git a/src/_node/file/types.ts b/src/_node/file/types.ts index 9de0ce63..103b8c12 100644 --- a/src/_node/file/types.ts +++ b/src/_node/file/types.ts @@ -1,18 +1,13 @@ +import { Dispatch } from "react"; + import JSZip from "jszip"; import { TOsType } from "@_redux/global"; - -import { - TBasicNodeData, - TNode, - TNodeActionType, - TNodeTreeData, - TNodeUid, -} from "../"; import { TFileActionType, TProjectContext } from "@_redux/main/fileTree"; -import { AnyAction } from "@reduxjs/toolkit"; -import { Dispatch } from "react"; import { TClipboardData } from "@_redux/main/processor"; +import { AnyAction } from "@reduxjs/toolkit"; + +import { TBasicNodeData, TNode, TNodeTreeData, TNodeUid } from "../"; export type TFileNode = TNode & { data: TFileNodeData; @@ -86,21 +81,20 @@ export type TFileApiPayloadBase = { fileTree: TFileNodeTreeData; fileHandlers?: TFileHandlerCollection; osType?: TOsType; - newName?: string; }; export type TFileApiPayload = TFileApiPayloadBase & ( | { action: Extract< TFileActionType, - "remove" | "cut" | "move" | "copy" | "rename" + "remove" | "cut" | "copy" | "move" | "rename" >; uids: TNodeUid[]; } | { action: Exclude< TFileActionType, - "remove" | "cut" | "move" | "copy" | "rename" + "remove" | "cut" | "copy" | "move" | "rename" >; uids?: never; } @@ -108,20 +102,15 @@ export type TFileApiPayload = TFileApiPayloadBase & ( | { action: Extract; - currentFileUid: string; + currentFileUid: TNodeUid; + nodeTree: TNodeTreeData; } | { action: Exclude; currentFileUid?: never; + nodeTree?: never; } ) & - ( - | { - action: Extract; - nodeTree: TNodeTreeData; - } - | { action: Exclude; nodeTree?: never } - ) & ( | { action: Extract; diff --git a/src/components/main/actionsPanel/workspaceTreeView/WorkspaceTreeView.tsx b/src/components/main/actionsPanel/workspaceTreeView/WorkspaceTreeView.tsx index b1faf600..31f993e9 100644 --- a/src/components/main/actionsPanel/workspaceTreeView/WorkspaceTreeView.tsx +++ b/src/components/main/actionsPanel/workspaceTreeView/WorkspaceTreeView.tsx @@ -11,28 +11,26 @@ import { debounce } from "lodash"; import { DraggingPositionItem } from "react-complex-tree"; import { useDispatch } from "react-redux"; -import { SVGIconI, TreeView } from "@_components/common"; +import { SVGIconI, SVGIconII, TreeView } from "@_components/common"; import { getNormalizedPath, TFileNodeData } from "@_node/file"; import { _path } from "@_node/file/nohostApis"; import { TNode, TNodeUid } from "@_node/types"; import { MainContext } from "@_redux/main"; import { setHoveredFileUid } from "@_redux/main/fileTree"; import { FileTree_Event_ClearActionType } from "@_redux/main/fileTree/event"; -import { setActivePanel, setDidRedo, setDidUndo } from "@_redux/main/processor"; +import { setActivePanel } from "@_redux/main/processor"; import { useAppState } from "@_redux/useAppState"; import { generateQuerySelector } from "@_services/main"; import { TFilesReference } from "@_types/main"; import { useCmdk, - useFileOperations, useInvalidNodes, useNodeActionsHandler, useNodeViewState, useSync, useTemporaryNodes, } from "./hooks"; -import { Container, ItemArrow } from "./workSpaceTreeComponents"; import { useDefaultFileCreate } from "./hooks/useDefaultFile"; const AutoExpandDelayOnDnD = 1 * 1000; @@ -81,14 +79,6 @@ export default function WorkspaceTreeView() { const { cb_focusNode, cb_selectNode, cb_expandNode, cb_collapseNode } = useNodeViewState({ invalidNodes }); - const { _create, _delete, _cut, _copy, _rename } = useFileOperations({ - invalidNodes, - addInvalidNodes, - removeInvalidNodes, - temporaryNodes, - addTemporaryNodes, - removeTemporaryNodes, - }); const openFileUid = useRef(""); const { cb_startRenamingNode, @@ -279,8 +269,12 @@ export default function WorkspaceTreeView() { expandedItems={expandedItems} selectedItems={selectedItems} renderers={{ - renderTreeContainer: (props) => , - renderItemsContainer: (props) => , + renderTreeContainer: ({ containerProps, children }) => { + return
    {children}
; + }, + renderItemsContainer: ({ containerProps, children }) => { + return
    {children}
; + }, renderItem: (props) => { useEffect(() => { @@ -469,7 +463,21 @@ export default function WorkspaceTreeView() { ); }, - renderItemArrow: (props) => , + renderItemArrow: ({ item, context }) => { + return ( + <> + {item.isFolder ? ( + context.isExpanded ? ( + down + ) : ( + right + ) + ) : ( +
+ )} + + ); + }, renderItemTitle: (props) => { const fileOrDirectoryTitle = props?.title; const fileExt = !!props.item?.data?.data?.ext diff --git a/src/components/main/actionsPanel/workspaceTreeView/errors.ts b/src/components/main/actionsPanel/workspaceTreeView/errors.ts deleted file mode 100644 index 1deaaa26..00000000 --- a/src/components/main/actionsPanel/workspaceTreeView/errors.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { TToast } from "@_types/index"; - -export const folderError: TToast = { - type: "error", - content: "Error occurred while creating a new folder.", -}; - -export const fileError: TToast = { - type: "error", - content: "Error occurred while creating a new file.", -}; - -export const renamingError: TToast = { - type: "error", - content: "Error occurred while renaming ...", -}; - -export const deletingWarning: TToast = { - type: "warning", - content: "Some directory/file couldn't be deleted.", -}; - -export const invalidDirError: TToast = { - type: "error", - content: `Invalid target directory. Check if you have "write" permission for the directory.`, -}; - -export const movingError: TToast = { - type: "warning", - content: "Some directory/file couldn't be moved.", -}; - -export const duplicatingWarning: TToast = { - type: "warning", - content: "Some directory/file couldn't be duplicated.", -}; - -export const invalidDirOrFile: TToast = { - type: "error", - content: `Invalid directory/file. Check if you have "write" permission for the directory/file.`, -}; diff --git a/src/components/main/actionsPanel/workspaceTreeView/helpers/copyDirectory.ts b/src/components/main/actionsPanel/workspaceTreeView/helpers/copyDirectory.ts deleted file mode 100644 index 36ea2c08..00000000 --- a/src/components/main/actionsPanel/workspaceTreeView/helpers/copyDirectory.ts +++ /dev/null @@ -1,42 +0,0 @@ -export const copyDirectory = async ( - source: FileSystemDirectoryHandle, - destination: FileSystemDirectoryHandle, - copy: boolean, -) => { - const dirQueue = [ - { - source, - destination, - }, - ]; - - while (dirQueue.length) { - const { source, destination } = dirQueue.shift() as { - source: FileSystemDirectoryHandle; - destination: FileSystemDirectoryHandle; - }; - - for await (const entry of source.values()) { - if (entry.kind === "directory") { - const newDir = await destination.getDirectoryHandle(entry.name, { - create: true, - }); - dirQueue.push({ - source: entry as FileSystemDirectoryHandle, - destination: newDir, - }); - } else { - const newFile = await destination.getFileHandle(entry.name, { - create: true, - }); - const content = await (entry as FileSystemFileHandle).getFile(); - const writableStream = await newFile.createWritable(); - await writableStream.write(content); - await writableStream.close(); - } - } - } - - // Handle copy (optional) - !copy && (await source.removeEntry(destination.name, { recursive: true })); -}; diff --git a/src/components/main/actionsPanel/workspaceTreeView/helpers/createDefaultFile.ts b/src/components/main/actionsPanel/workspaceTreeView/helpers/createDefaultFile.ts deleted file mode 100644 index 55173bfe..00000000 --- a/src/components/main/actionsPanel/workspaceTreeView/helpers/createDefaultFile.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { RootNodeUid } from "@_constants/index"; -import { TFileHandlerCollection, getIndexHtmlContent } from "@_node/index"; - -export const createDefaultFile = async ( - fileHandlers: TFileHandlerCollection, -) => { - const indexHtmlContent = getIndexHtmlContent(); - const newFile = await ( - fileHandlers[RootNodeUid] as FileSystemDirectoryHandle - ).getFileHandle("index.html", { - create: true, - }); - const writableStream = await newFile.createWritable(); - await writableStream.write(indexHtmlContent); - await writableStream.close(); -}; diff --git a/src/components/main/actionsPanel/workspaceTreeView/helpers/createFileOrFolder.ts b/src/components/main/actionsPanel/workspaceTreeView/helpers/createFileOrFolder.ts deleted file mode 100644 index 256a2e7a..00000000 --- a/src/components/main/actionsPanel/workspaceTreeView/helpers/createFileOrFolder.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { - TFileHandlerCollection, - TFileNodeData, -} from "@_node/file"; -import { _createIDBDirectory, _writeIDBFile } from "@_node/file/nohostApis"; -import { TNodeTreeData, TNodeUid } from "@_node/types"; -import { TProject } from "@_redux/main/fileTree"; -import { verifyFileHandlerPermission } from "@_services/main"; -import { TFileNodeType } from "@_types/main"; - -export const createFileOrFolder = async ( - parentUid: TNodeUid, - name: string, - type: TFileNodeType, - project: Omit, - ffTree: TNodeTreeData, - fileHandlers: TFileHandlerCollection, -) => { - try { - const parentNode = ffTree[parentUid]; - if (parentNode === undefined) throw new Error("Parent node not found"); - const parentNodeData = parentNode.data as TFileNodeData; - - if (project.context === "local") { - const parentHandler = fileHandlers[ - parentNode.uid - ] as FileSystemDirectoryHandle; - if (!(await verifyFileHandlerPermission(parentHandler))) { - throw new Error("Permission denied"); - } - - if (type === "*folder") { - await parentHandler.getDirectoryHandle(name, { create: true }); - } else { - await parentHandler.getFileHandle(name, { create: true }); - } - } else if (project.context === "idb") { - if (type === "*folder") { - await _createIDBDirectory(`${parentNodeData.path}/${name}`); - } else { - await _writeIDBFile(`${parentNodeData.path}/${name}`, ""); - } - } - } catch (err) { - console.error(err); - } -}; diff --git a/src/components/main/actionsPanel/workspaceTreeView/helpers/deleteFileOrFolder.ts b/src/components/main/actionsPanel/workspaceTreeView/helpers/deleteFileOrFolder.ts deleted file mode 100644 index bf3eb6d8..00000000 --- a/src/components/main/actionsPanel/workspaceTreeView/helpers/deleteFileOrFolder.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { - TFileHandlerCollection, - TFileNodeData, -} from "@_node/file"; -import { _removeIDBDirectoryOrFile } from "@_node/file/nohostApis"; -import { TNodeUid } from "@_node/types"; -import { verifyFileHandlerPermission } from "@_services/main"; - -export const deleteFileOrFolder = async ( - uid: TNodeUid, - ffTree: Record, - fileHandlers: TFileHandlerCollection, - projectContext: string, -) => { - try { - // validate - const node = ffTree[uid]; - if (node === undefined) throw new Error("Node not found"); - const nodeData = node.data as TFileNodeData; - const parentNode = ffTree[node.parentUid as TNodeUid]; - if (parentNode === undefined) throw new Error("Parent node not found"); - const parentNodeData = parentNode.data as TFileNodeData; - - if (projectContext === "local") { - const parentHandler = fileHandlers[ - parentNode.uid - ] as FileSystemDirectoryHandle; - if (!(await verifyFileHandlerPermission(parentHandler))) { - throw new Error("Permission denied"); - } - - // delete - try { - const entryName = - nodeData.kind === "directory" - ? nodeData.name - : `${nodeData.name}${nodeData.ext}`; - await parentHandler.removeEntry(entryName, { recursive: true }); - } catch (err) { - console.error(err); - } - } else if (projectContext === "idb") { - // delete - try { - const entryName = - nodeData.kind === "directory" - ? nodeData.name - : `${nodeData.name}${nodeData.ext}`; - await _removeIDBDirectoryOrFile(`${parentNodeData.path}/${entryName}`); - } catch (err) { - console.error(err); - } - } - } catch (err) { - console.error(err); - } -}; diff --git a/src/components/main/actionsPanel/workspaceTreeView/helpers/duplicateNode.ts b/src/components/main/actionsPanel/workspaceTreeView/helpers/duplicateNode.ts deleted file mode 100644 index 6cd305f9..00000000 --- a/src/components/main/actionsPanel/workspaceTreeView/helpers/duplicateNode.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { - TFileHandlerCollection, - TFileNodeData, - moveLocalFF, -} from "@_node/file"; -import { TNodeTreeData, TNodeUid } from "@_node/types"; -import { verifyFileHandlerPermission } from "@_services/main"; -import { TToast } from "@_types/global"; - -import { duplicatingWarning, invalidDirError } from "../errors"; -import { generateNewNodeName } from "./"; - -export const duplicateNode = async ( - uid: TNodeUid, - isCopy: boolean, - ffTree: TNodeTreeData, - fileHandlers: TFileHandlerCollection, - addMessage: (message: TToast) => void, - addInvalidNodes: any, - invalidNodes: { [uid: string]: boolean }, -) => { - const node = ffTree[uid]; - if (!node) return; - - const nodeData = node.data as TFileNodeData; - const parentNode = ffTree[node.parentUid as TNodeUid]; - if (!parentNode) return; - - const parentHandler = fileHandlers[ - parentNode.uid - ] as FileSystemDirectoryHandle; - - if (!(await verifyFileHandlerPermission(parentHandler))) { - addMessage(invalidDirError); - return; - } - - const newName = await generateNewNodeName( - parentHandler, - nodeData.name, - nodeData.kind === "directory", - nodeData.ext, - ); - - const newUid = `${node.parentUid}/${newName}`; - addInvalidNodes({ ...invalidNodes, [uid]: true, [newUid]: true }); - - try { - await moveLocalFF( - fileHandlers[uid], - parentHandler, - parentHandler, - newName, - true, - ); - } catch (err) { - addMessage(duplicatingWarning); - } - - delete invalidNodes[uid]; - delete invalidNodes[newUid]; - addInvalidNodes({ ...invalidNodes }); - - return { uid, name: newName }; -}; diff --git a/src/components/main/actionsPanel/workspaceTreeView/helpers/generateNewName.ts b/src/components/main/actionsPanel/workspaceTreeView/helpers/generateNewName.ts deleted file mode 100644 index cb4767b4..00000000 --- a/src/components/main/actionsPanel/workspaceTreeView/helpers/generateNewName.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { TFileNodeType } from "@_types/main"; - -export const generateNewName = async ( - parentHandler: FileSystemDirectoryHandle | undefined, - ffType: TFileNodeType, - ffName: string, -) => { - if (!parentHandler) return ffName; - - let newName = ffName; - let exists = true; - - const checkExists = async (name: string) => { - try { - if (ffType === "*folder") { - await parentHandler.getDirectoryHandle(name, { create: false }); - } else { - await parentHandler.getFileHandle(name, { create: false }); - } - return true; - } catch (err) { - return false; - } - }; - - if (await checkExists(newName)) { - let index = 0; - while (exists) { - const _name = - ffType === "*folder" - ? `${ffName} (${++index})` - : `${ffName} (${++index}).${ffType}`; - if (!(await checkExists(_name))) { - newName = _name; - exists = false; - } - } - } - - return newName; -}; diff --git a/src/components/main/actionsPanel/workspaceTreeView/helpers/generateNewNameMoveNode.ts b/src/components/main/actionsPanel/workspaceTreeView/helpers/generateNewNameMoveNode.ts deleted file mode 100644 index 57ee7162..00000000 --- a/src/components/main/actionsPanel/workspaceTreeView/helpers/generateNewNameMoveNode.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { TFileNodeData } from "@_node/file"; - -export const generateNewNameMoveNode = async ( - nodeData: TFileNodeData, - targetHandler: FileSystemDirectoryHandle, -) => { - let newName = - nodeData.kind === "directory" - ? nodeData.name - : `${nodeData.name}.${nodeData.ext}`; - - if (nodeData.kind === "directory") { - let folderName = nodeData.name; - let exists = false; - try { - await targetHandler.getDirectoryHandle(folderName, { - create: false, - }); - exists = true; - } catch (err) { - exists = false; - } - if (exists) { - try { - folderName = `${nodeData.name} copy`; - await targetHandler.getDirectoryHandle(folderName, { - create: false, - }); - exists = true; - } catch (err) { - exists = false; - } - if (exists) { - let index = 0; - while (exists) { - try { - folderName = `${nodeData.name} copy (${++index})`; - await targetHandler.getDirectoryHandle(folderName, { - create: false, - }); - exists = true; - } catch (err) { - exists = false; - } - } - } - } - newName = folderName; - } else { - let fileName = `${nodeData.name}.${nodeData.ext}`; - let exists = false; - try { - await targetHandler.getFileHandle(fileName, { - create: false, - }); - exists = true; - } catch (err) { - exists = false; - } - if (exists) { - try { - fileName = `${nodeData.name} copy.${nodeData.ext}`; - await targetHandler.getFileHandle(fileName, { - create: false, - }); - exists = true; - } catch (err) { - exists = false; - } - if (exists) { - let index = 0; - while (exists) { - try { - fileName = `${nodeData.name} copy (${++index}).${nodeData.ext}`; - await targetHandler.getFileHandle(fileName, { - create: false, - }); - exists = true; - } catch (err) { - exists = false; - } - } - } - newName = fileName; - } - } - - return newName; -}; diff --git a/src/components/main/actionsPanel/workspaceTreeView/helpers/generateNewNodeName.ts b/src/components/main/actionsPanel/workspaceTreeView/helpers/generateNewNodeName.ts deleted file mode 100644 index 832d51b2..00000000 --- a/src/components/main/actionsPanel/workspaceTreeView/helpers/generateNewNodeName.ts +++ /dev/null @@ -1,32 +0,0 @@ -export const generateNewNodeName = async ( - parentNode: FileSystemDirectoryHandle, - baseName: string, - isDirectory: boolean, - ext: string, -) => { - let newName = isDirectory ? `${baseName} copy` : `${baseName} copy${ext}`; - let exists = true; - let index = 0; - - while (exists) { - try { - if (isDirectory) { - await parentNode.getDirectoryHandle(newName, { create: false }); - } else { - await parentNode.getFileHandle(newName, { create: false }); - } - exists = true; - } catch (err) { - exists = false; - } - - if (exists) { - index++; - newName = isDirectory - ? `${baseName} copy (${index})` - : `${baseName} copy (${index})${ext}`; - } - } - - return newName; -}; diff --git a/src/components/main/actionsPanel/workspaceTreeView/helpers/index.ts b/src/components/main/actionsPanel/workspaceTreeView/helpers/index.ts deleted file mode 100644 index 55ead0df..00000000 --- a/src/components/main/actionsPanel/workspaceTreeView/helpers/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -export * from "./copyDirectory"; -export * from "./moveDirectory"; -export * from "./createFileOrFolder"; -export * from "./deleteFileOrFolder"; -export * from "./generateNewName"; -export * from "./renameNode"; -export * from "./generateNewNameMoveNode"; -export * from "./duplicateNode"; -export * from "./generateNewNodeName"; diff --git a/src/components/main/actionsPanel/workspaceTreeView/helpers/moveDirectory.ts b/src/components/main/actionsPanel/workspaceTreeView/helpers/moveDirectory.ts deleted file mode 100644 index be02ef42..00000000 --- a/src/components/main/actionsPanel/workspaceTreeView/helpers/moveDirectory.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { TFileNodeData } from "@_node/file"; -import { - _createIDBDirectory, - _getIDBDirectoryOrFileStat, - _readIDBDirectory, - _readIDBFile, - _removeIDBDirectoryOrFile, - _writeIDBFile, -} from "@_node/file/nohostApis"; - -export const moveDirectory = async ( - orgPath: string, - newPath: string, - copy: boolean, - nodeData: TFileNodeData, -) => { - const dirs = [ - { - orgPath, - newPath, - }, - ]; - - while (dirs.length) { - const { orgPath, newPath } = dirs.shift() as { - orgPath: string; - newPath: string; - }; - await _createIDBDirectory(newPath); - - const entries = await _readIDBDirectory(orgPath); - await Promise.all( - entries.map(async (entry) => { - const c_orgPath = `${orgPath}/${entry}`; - const c_newPath = `${newPath}/${entry}`; - const stats = await _getIDBDirectoryOrFileStat(c_orgPath); - const c_kind = stats.type === "DIRECTORY" ? "directory" : "file"; - if (c_kind === "directory") { - dirs.push({ orgPath: c_orgPath, newPath: c_newPath }); - } else { - await _writeIDBFile(c_newPath, await _readIDBFile(c_orgPath)); - } - }), - ); - } - - // handle copy(optional) - !copy && (await _removeIDBDirectoryOrFile(nodeData.path)); -}; diff --git a/src/components/main/actionsPanel/workspaceTreeView/helpers/renameNode.ts b/src/components/main/actionsPanel/workspaceTreeView/helpers/renameNode.ts deleted file mode 100644 index 10696312..00000000 --- a/src/components/main/actionsPanel/workspaceTreeView/helpers/renameNode.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { useContext } from "react"; - -import { useDispatch } from "react-redux"; - -import { TFileNodeData, moveIDBFF, moveLocalFF } from "@_node/file"; -import { TNode, TNodeUid } from "@_node/types"; -import { MainContext } from "@_redux/main"; -import { - setCurrentFileUid, - updateFileTreeViewState, -} from "@_redux/main/fileTree"; -import { setFileAction, TFileAction } from "@_redux/main/fileTree/event"; -import { useAppState } from "@_redux/useAppState"; -import { verifyFileHandlerPermission } from "@_services/main"; - -import { useInvalidNodes } from "../hooks"; - -export const renameNode = async ( - ext: string, - newName: string, - nodeData: TFileNodeData, - parentNode: TNode, - parentNodeData: TFileNodeData, - uid: TNodeUid, -) => { - const dispatch = useDispatch(); - - const { project } = useAppState(); - - const { removeRunningActions, fileHandlers } = useContext(MainContext); - - const { removeInvalidNodes, addInvalidNodes } = useInvalidNodes(); - - const _orgName = - ext === "*folder" ? `${nodeData.name}` : `${nodeData.name}${nodeData.ext}`; - - const _newName = ext === "*folder" ? `${newName}` : `${newName}${ext}`; - - const newUid = `${parentNode.uid}/${_newName}`; - - if (project.context === "local") { - const handler = fileHandlers[uid], - parentHandler = fileHandlers[parentNode.uid] as FileSystemDirectoryHandle; - if ( - !(await verifyFileHandlerPermission(handler)) || - !(await verifyFileHandlerPermission(parentHandler)) - ) { - // addMessage(invalidDirOrFile); - - removeRunningActions(["fileTreeView-rename"]); - return; - } - - addInvalidNodes(newUid); - - try { - await moveLocalFF( - handler, - parentHandler, - parentHandler, - _newName, - false, - true, - ); - removeInvalidNodes(newUid); - } catch (err) { - // addMessage(renamingError); - - removeInvalidNodes(newUid); - removeRunningActions(["fileTreeView-rename"]); - return; - } - } else if (project.context === "idb") { - addInvalidNodes(newUid); - - try { - await moveIDBFF(nodeData, parentNodeData, _newName, false); - removeInvalidNodes(newUid); - } catch (err) { - // addMessage(renamingError); - - removeInvalidNodes(newUid); - removeRunningActions(["fileTreeView-rename"]); - return; - } - } - - /* const action: TFileAction = { - type: "rename", - param1: { uid, parentUid: parentNode.uid }, - param2: { orgName: _orgName, newName: _newName }, - }; - dispatch(setFileAction(action)); */ - - // update redux - dispatch(setCurrentFileUid(newUid)); - dispatch(updateFileTreeViewState({ convertedUids: [[uid, newUid]] })); - - removeRunningActions(["fileTreeView-rename"]); -}; diff --git a/src/components/main/actionsPanel/workspaceTreeView/hooks/index.ts b/src/components/main/actionsPanel/workspaceTreeView/hooks/index.ts index fce824a6..11a59471 100644 --- a/src/components/main/actionsPanel/workspaceTreeView/hooks/index.ts +++ b/src/components/main/actionsPanel/workspaceTreeView/hooks/index.ts @@ -1,6 +1,5 @@ export * from "./useInvalidNodes"; export * from "./useTemporaryNodes"; -export * from "./useFileOperations"; export * from "./useNodeActionsHandler"; export * from "./useNodeViewState"; export * from "./useCmdk"; diff --git a/src/components/main/actionsPanel/workspaceTreeView/hooks/useCmdk.ts b/src/components/main/actionsPanel/workspaceTreeView/hooks/useCmdk.ts index a7de8cf1..7c04b068 100644 --- a/src/components/main/actionsPanel/workspaceTreeView/hooks/useCmdk.ts +++ b/src/components/main/actionsPanel/workspaceTreeView/hooks/useCmdk.ts @@ -1,17 +1,11 @@ -import { useCallback, useContext, useEffect } from "react"; - -import { useDispatch } from "react-redux"; +import { useCallback, useEffect } from "react"; import { AddFileActionPrefix } from "@_constants/main"; -import { setClipboardData } from "@_redux/main/processor"; +import { isAddFileAction } from "@_node/helpers"; import { useAppState } from "@_redux/useAppState"; import { TFileNodeType } from "@_types/main"; import { useNodeActionsHandler } from "./useNodeActionsHandler"; -import { isAddFileAction } from "@_node/helpers"; -import { TFileApiPayload, doFileActions } from "@_node/index"; -import { MainContext } from "@_redux/main"; -import { LogAllow } from "@_constants/global"; interface IUseCmdk { invalidNodes: { @@ -35,21 +29,9 @@ export const useCmdk = ({ removeTemporaryNodes, openFileUid, }: IUseCmdk) => { - const dispatch = useDispatch(); - const { - activePanel, - currentFileUid, - fFocusedItem: focusedItem, - fSelectedItems: selectedItems, - clipboardData, - fileTree, - nodeTree, - currentCommand, - } = useAppState(); + const { activePanel, currentCommand } = useAppState(); - const { fileHandlers, reloadCurrentProject, currentProjectFileHandle } = - useContext(MainContext); - const { createTmpFFNode } = useNodeActionsHandler({ + const { createTmpNode, onDelete } = useNodeActionsHandler({ invalidNodes, addInvalidNodes, removeInvalidNodes, @@ -62,113 +44,28 @@ export const useCmdk = ({ const onAddNode = useCallback( (actionName: string) => { const nodeType = actionName.slice(AddFileActionPrefix.length + 1); - createTmpFFNode( + createTmpNode( nodeType === "folder" ? "*folder" : (nodeType as TFileNodeType), ); }, - [createTmpFFNode], + [createTmpNode], ); - const onCopy = useCallback(() => { - const params: TFileApiPayload = { - projectContext: "local", - action: "copy", - uids: selectedItems, - fileTree, - fileHandlers, - dispatch, - currentFileUid, - nodeTree, - }; - doFileActions(params); - }, [selectedItems, fileTree[currentFileUid], nodeTree]); - - const onPaste = useCallback(() => { - if (clipboardData?.panel !== "file") return; - - // validate - if (invalidNodes[focusedItem]) return; - const uids = clipboardData.uids.filter((uid) => !invalidNodes[uid]); - if (uids.length === 0) return; - const params: TFileApiPayload = { - projectContext: "local", - fileHandlers, - uids, - clipboardData, - fileTree, - action: "move", - targetNode: fileTree[focusedItem], - }; - doFileActions( - params, - () => { - LogAllow && console.error("error while removing file system"); - }, - (allDone: boolean) => { - reloadCurrentProject(); - LogAllow && - console.log( - allDone ? "all is successfully removed" : "some is not removed", - ); - }, - ); - }, [clipboardData, selectedItems, fileTree[currentFileUid], nodeTree]); - - const onDuplicate = useCallback(() => { - onCopy(); - onPaste(); - }, [selectedItems, fileTree[currentFileUid], nodeTree, clipboardData]); - - const onDelete = useCallback(() => { - const params: TFileApiPayload = { - projectContext: "local", - action: "remove", - uids: selectedItems, - fileTree, - fileHandlers, - }; - doFileActions( - params, - () => { - LogAllow && console.error("error while removing file system"); - }, - (allDone: boolean) => { - reloadCurrentProject(); - LogAllow && - console.log( - allDone ? "all is successfully removed" : "some is not removed", - ); - }, - ); - }, [selectedItems, fileTree[currentFileUid], nodeTree]); - - const onCut = useCallback(() => { - const params: TFileApiPayload = { - projectContext: "local", - action: "cut", - uids: selectedItems, - fileTree, - fileHandlers, - dispatch, - currentFileUid, - nodeTree, - }; - doFileActions(params); - }, [selectedItems, fileTree[currentFileUid], nodeTree, clipboardData]); - useEffect(() => { if (!currentCommand) return; + if (isAddFileAction(currentCommand.action)) { onAddNode(currentCommand.action); return; } + if (activePanel !== "file") return; switch (currentCommand.action) { case "Delete": onDelete(); break; - case "Cut": + /* case "Cut": onCut(); break; case "Copy": @@ -179,7 +76,7 @@ export const useCmdk = ({ break; case "Duplicate": onDuplicate(); - break; + break; */ default: break; } diff --git a/src/components/main/actionsPanel/workspaceTreeView/hooks/useDefaultFile.tsx b/src/components/main/actionsPanel/workspaceTreeView/hooks/useDefaultFile.tsx index 0c363395..ca1c30e2 100644 --- a/src/components/main/actionsPanel/workspaceTreeView/hooks/useDefaultFile.tsx +++ b/src/components/main/actionsPanel/workspaceTreeView/hooks/useDefaultFile.tsx @@ -4,7 +4,7 @@ import { setShowActionsPanel } from "@_redux/main/processor"; import { useAppState } from "@_redux/useAppState"; import { useContext, useEffect } from "react"; import { useDispatch } from "react-redux"; -import { createDefaultFile } from "../helpers/createDefaultFile"; +// import { createDefaultFile } from "../helpers/createDefaultFile"; export const useDefaultFileCreate = () => { const { fileTree } = useAppState(); @@ -17,7 +17,7 @@ export const useDefaultFileCreate = () => { fileTree[RootNodeUid]?.children?.length === 0 && fileHandlers[RootNodeUid] ) { - createDefaultFile(fileHandlers); + // createDefaultFile(fileHandlers); reloadCurrentProject(); dispatch(setShowActionsPanel(true)); } diff --git a/src/components/main/actionsPanel/workspaceTreeView/hooks/useFileOperations.ts b/src/components/main/actionsPanel/workspaceTreeView/hooks/useFileOperations.ts deleted file mode 100644 index d1f8e783..00000000 --- a/src/components/main/actionsPanel/workspaceTreeView/hooks/useFileOperations.ts +++ /dev/null @@ -1,302 +0,0 @@ -import { useCallback, useContext } from "react"; - -import { TFileNodeData, moveIDBFF, moveLocalFF } from "@_node/file"; -import { TNodeUid } from "@_node/types"; -import { MainContext } from "@_redux/main"; -import { useAppState } from "@_redux/useAppState"; -import { verifyFileHandlerPermission } from "@_services/main"; -import { TFileNodeType } from "@_types/main"; - -import { createFileOrFolder, deleteFileOrFolder } from "../helpers"; -import { LogAllow } from "@_constants/global"; - -interface IUseFileOperations { - invalidNodes: { - [uid: string]: true; - }; - addInvalidNodes: (...uids: string[]) => void; - removeInvalidNodes: (...uids: string[]) => void; - temporaryNodes: { - [uid: string]: true; - }; - addTemporaryNodes: (...uids: string[]) => void; - removeTemporaryNodes: (...uids: string[]) => void; -} -export const useFileOperations = ({ - invalidNodes, - addInvalidNodes, - removeInvalidNodes, - temporaryNodes, - addTemporaryNodes, - removeTemporaryNodes, -}: IUseFileOperations) => { - const { project, fileTree } = useAppState(); - const { addRunningActions, removeRunningActions, fileHandlers } = - useContext(MainContext); - - const _create = useCallback( - async (params: { - parentUid: TNodeUid; - name: string; - type: TFileNodeType; - }) => { - addRunningActions(["fileTreeView-create"]); - - const { parentUid, name, type } = params; - try { - await createFileOrFolder( - parentUid, - name, - type, - project, - fileTree, - fileHandlers, - ); - } catch (err) { - throw new Error("err"); - } - - removeRunningActions(["fileTreeView-create"]); - }, - [ - addRunningActions, - removeRunningActions, - project.context, - fileTree, - fileHandlers, - ], - ); - const _delete = useCallback( - async (uids: TNodeUid[]) => { - addRunningActions(["fileTreeView-delete"]); - addInvalidNodes(...uids); - - await Promise.all( - uids.map(async (uid) => { - try { - await deleteFileOrFolder( - uid, - fileTree, - fileHandlers, - project.context, - ); - } catch (err) { - console.error(err); - } - }), - ); - - removeInvalidNodes(...uids); - removeRunningActions(["fileTreeView-delete"]); - }, - [ - addRunningActions, - removeRunningActions, - project.context, - addInvalidNodes, - removeInvalidNodes, - fileTree, - fileHandlers, - ], - ); - const _rename = useCallback( - async (uid: TNodeUid, newName: string) => { - addRunningActions(["fileTreeView-rename"]); - - try { - // validate - const node = fileTree[uid]; - if (node === undefined || node.displayName === newName) throw "error"; - const nodeData = node.data as TFileNodeData; - const parentNode = fileTree[node.parentUid as TNodeUid]; - if (parentNode === undefined) throw "error"; - const parentNodeData = parentNode.data as TFileNodeData; - - const newUid = `${parentNode.uid}/${newName}`; - addTemporaryNodes(uid); - addInvalidNodes(newUid); - - if (project.context === "local") { - const handler = fileHandlers[uid], - parentHandler = fileHandlers[ - parentNode.uid - ] as FileSystemDirectoryHandle; - if ( - !(await verifyFileHandlerPermission(handler)) || - !(await verifyFileHandlerPermission(parentHandler)) - ) - throw "error"; - - await moveLocalFF(handler, parentHandler, parentHandler, newName); - } else if (project.context === "idb") { - await moveIDBFF(nodeData, parentNodeData, newName); - } - - removeInvalidNodes(newUid); - removeTemporaryNodes(uid); - } catch (err) {} - removeRunningActions(["fileTreeView-rename"]); - }, - [ - addRunningActions, - removeRunningActions, - project.context, - addTemporaryNodes, - removeTemporaryNodes, - addInvalidNodes, - removeInvalidNodes, - fileTree, - fileHandlers, - ], - ); - const _cut = useCallback( - async (uids: TNodeUid[], targetUids: TNodeUid[]) => { - addRunningActions(["fileTreeView-move"]); - - const _invalidNodes = { ...invalidNodes }; - - await Promise.all( - uids.map(async (uid, index) => { - const targetUid = targetUids[index]; - - // validate - const node = fileTree[uid]; - if (node === undefined) return; - const nodeData = node.data as TFileNodeData; - const parentNode = fileTree[node.parentUid as TNodeUid]; - if (parentNode === undefined) return; - const targetNode = fileTree[targetUid]; - if (targetNode === undefined) return; - const targetNodeData = targetNode.data as TFileNodeData; - - const newUid = `${targetUid}/${nodeData.name}`; - _invalidNodes[uid] = true; - _invalidNodes[newUid] = true; - addInvalidNodes(...Object.keys(_invalidNodes)); - - if (project.context === "local") { - const handler = fileHandlers[uid], - parentHandler = fileHandlers[ - parentNode.uid - ] as FileSystemDirectoryHandle, - targetHandler = fileHandlers[ - targetUid - ] as FileSystemDirectoryHandle; - if ( - !(await verifyFileHandlerPermission(handler)) || - !(await verifyFileHandlerPermission(parentHandler)) || - !(await verifyFileHandlerPermission(targetHandler)) - ) - return; - - try { - await moveLocalFF( - handler, - parentHandler, - targetHandler, - nodeData.name, - ); - } catch (err) {} - } else if (project.context === "idb") { - await moveIDBFF(nodeData, targetNodeData, nodeData.name); - } - - delete _invalidNodes[uid]; - delete _invalidNodes[newUid]; - addInvalidNodes(...Object.keys(_invalidNodes)); - }), - ); - removeRunningActions(["fileTreeView-move"]); - }, - [ - addRunningActions, - removeRunningActions, - project.context, - invalidNodes, - addInvalidNodes, - fileTree, - fileHandlers, - ], - ); - const _copy = useCallback( - async (uids: TNodeUid[], names: string[], targetUids: TNodeUid[]) => { - addRunningActions(["fileTreeView-duplicate"]); - - const _invalidNodes = { ...invalidNodes }; - - await Promise.all( - uids.map(async (uid, index) => { - const name = names[index]; - const targetUid = targetUids[index]; - - // validate - const node = fileTree[uid]; - if (node === undefined) return; - const nodeData = node.data as TFileNodeData; - const parentNode = fileTree[node.parentUid as TNodeUid]; - if (parentNode === undefined) return; - const targetNode = fileTree[targetUid]; - if (targetNode === undefined) return; - const targetNodeData = targetNode.data as TFileNodeData; - - const newUid = `${targetUid}/${name}`; - _invalidNodes[uid] = true; - _invalidNodes[newUid] = true; - addInvalidNodes(...Object.keys(_invalidNodes)); - - if (project.context === "local") { - const handler = fileHandlers[uid], - parentHandler = fileHandlers[ - parentNode.uid - ] as FileSystemDirectoryHandle, - targetHandler = fileHandlers[ - targetUid - ] as FileSystemDirectoryHandle; - if ( - !(await verifyFileHandlerPermission(handler)) || - !(await verifyFileHandlerPermission(parentHandler)) || - !(await verifyFileHandlerPermission(targetHandler)) - ) - return; - - try { - await moveLocalFF( - handler, - parentHandler, - targetHandler, - name, - true, - ); - } catch (err) { - LogAllow && console.log(err); - } - } else if (project.context === "idb") { - await moveIDBFF(nodeData, targetNodeData, nodeData.name, true); - } - - delete _invalidNodes[uid]; - delete _invalidNodes[newUid]; - addInvalidNodes(...Object.keys(_invalidNodes)); - }), - ); - removeRunningActions(["fileTreeView-duplicate"]); - }, - [ - addRunningActions, - removeRunningActions, - project.context, - invalidNodes, - addInvalidNodes, - fileTree, - fileHandlers, - ], - ); - - return { - _copy, - _create, - _cut, - _delete, - _rename, - }; -}; diff --git a/src/components/main/actionsPanel/workspaceTreeView/hooks/useNodeActionsHandler.ts b/src/components/main/actionsPanel/workspaceTreeView/hooks/useNodeActionsHandler.ts index 94e3150f..ad7a6091 100644 --- a/src/components/main/actionsPanel/workspaceTreeView/hooks/useNodeActionsHandler.ts +++ b/src/components/main/actionsPanel/workspaceTreeView/hooks/useNodeActionsHandler.ts @@ -1,19 +1,21 @@ -import { useCallback, useContext } from "react"; +import { useCallback, useContext, useEffect, useState } from "react"; import { TreeItem } from "react-complex-tree"; import { useDispatch } from "react-redux"; +import { LogAllow } from "@_constants/global"; import { FileChangeAlertMessage, RednerableFileTypes, RootNodeUid, TmpNodeUid, } from "@_constants/main"; +import { callFileApi } from "@_node/apis"; import { _createIDBDirectory, - TFileNodeData, _writeIDBFile, confirmAlert, + TFileNodeData, } from "@_node/file"; import { getValidNodeUids } from "@_node/helpers"; import { TNode, TNodeTreeData, TNodeUid } from "@_node/types"; @@ -22,23 +24,18 @@ import { MainContext } from "@_redux/main"; import { expandFileTreeNodes, setCurrentFileUid, + setDoingFileAction, setFileTree, setPrevRenderableFileUid, } from "@_redux/main/fileTree"; -import { setFileAction, TFileAction } from "@_redux/main/fileTree/event"; import { setCurrentFileContent } from "@_redux/main/nodeTree/event"; import { setNavigatorDropdownType, setShowCodeView, } from "@_redux/main/processor"; import { useAppState } from "@_redux/useAppState"; -import { verifyFileHandlerPermission } from "@_services/main"; import { TFileNodeType } from "@_types/main"; -import { duplicateNode, generateNewName, renameNode } from "../helpers"; -import { callFileApi } from "@_node/apis"; -import { LogAllow } from "@_constants/global"; - interface IUseNodeActionsHandler { invalidNodes: { [uid: string]: true; @@ -82,9 +79,60 @@ export const useNodeActionsHandler = ({ reloadCurrentProject, } = useContext(MainContext); + const [reloadCurrentProjectTrigger, setReloadCurrentProjectTrigger] = + useState(false); + useEffect(() => { + reloadCurrentProject(); + }, [reloadCurrentProjectTrigger]); + + const onDelete = useCallback(async () => { + const uids = selectedItems.filter((uid) => !invalidNodes[uid]); + if (uids.length === 0) return; + + const message = `Are you sure you want to delete them? This action cannot be undone!`; + if (!window.confirm(message)) { + return; + } + + dispatch(setDoingFileAction(true)); + addInvalidNodes(...uids); + await callFileApi( + { + projectContext: project.context, + action: "remove", + fileTree, + fileHandlers, + uids, + }, + () => { + LogAllow && console.error("error while removing file system"); + }, + (allDone: boolean) => { + LogAllow && + console.log( + allDone ? "all is successfully removed" : "some is not removed", + ); + }, + ); + removeInvalidNodes(...uids); + dispatch(setDoingFileAction(false)); + + // reload the current project + setReloadCurrentProjectTrigger(true); + }, [ + selectedItems, + invalidNodes, + addInvalidNodes, + removeInvalidNodes, + project, + fileTree, + fileHandlers, + ]); + + // Add const createFFNode = useCallback( async (parentUid: TNodeUid, ffType: TFileNodeType, ffName: string) => { - let newName: string = ""; + /* let newName: string = ""; if (project.context === "local") { const parentHandler = fileHandlers[ @@ -123,7 +171,7 @@ export const useNodeActionsHandler = ({ removeRunningActions(["fileTreeView-create"]); return; } - } + } */ /* const action: TFileAction = { type: "create", @@ -136,7 +184,7 @@ export const useNodeActionsHandler = ({ }, [addRunningActions, removeRunningActions, project.context, fileHandlers], ); - const createTmpFFNode = useCallback( + const createTmpNode = useCallback( async (ffNodeType: TFileNodeType) => { const tmpTree = JSON.parse(JSON.stringify(fileTree)) as TNodeTreeData; @@ -205,33 +253,8 @@ export const useNodeActionsHandler = ({ removeInvalidNodes, ], ); - const cb_startRenamingNode = useCallback( - (uid: TNodeUid) => { - // validate - if (invalidNodes[uid]) { - removeInvalidNodes(uid); - return; - } - addInvalidNodes(uid); - }, - [invalidNodes, addInvalidNodes, removeInvalidNodes], - ); - const cb_abortRenamingNode = useCallback( - (item: TreeItem) => { - const node = item.data as TNode; - const nodeData = node.data as TFileNodeData; - if (!nodeData.valid) { - const tmpTree = structuredClone(fileTree); - tmpTree[node.parentUid as TNodeUid].children = tmpTree[ - node.parentUid as TNodeUid - ].children.filter((c_uid: TNodeUid) => c_uid !== node.uid); - delete tmpTree[item.data.uid]; - dispatch(setFileTree(tmpTree)); - } - removeInvalidNodes(node.uid); - }, - [fileTree, removeInvalidNodes], - ); + + // Rename const onRename = useCallback( async (uid: TNodeUid, newName: string) => { // validate @@ -271,6 +294,33 @@ export const useNodeActionsHandler = ({ fileHandlers, ], ); + const cb_startRenamingNode = useCallback( + (uid: TNodeUid) => { + // validate + if (invalidNodes[uid]) { + removeInvalidNodes(uid); + return; + } + addInvalidNodes(uid); + }, + [invalidNodes, addInvalidNodes, removeInvalidNodes], + ); + const cb_abortRenamingNode = useCallback( + (item: TreeItem) => { + const node = item.data as TNode; + const nodeData = node.data as TFileNodeData; + if (!nodeData.valid) { + const tmpTree = structuredClone(fileTree); + tmpTree[node.parentUid as TNodeUid].children = tmpTree[ + node.parentUid as TNodeUid + ].children.filter((c_uid: TNodeUid) => c_uid !== node.uid); + delete tmpTree[item.data.uid]; + dispatch(setFileTree(tmpTree)); + } + removeInvalidNodes(node.uid); + }, + [fileTree, removeInvalidNodes], + ); const cb_renameNode = useCallback( async (item: TreeItem, newName: string) => { const node = item.data as TNode; @@ -331,56 +381,6 @@ export const useNodeActionsHandler = ({ ); }, [selectedItems, fileTree[currentFileUid], nodeTree]); - const onDelete = useCallback(async () => { - const uids = selectedItems.filter((uid) => !invalidNodes[uid]); - if (uids.length === 0) return; - - const message = `Are you sure you want to delete them? This action cannot be undone!`; - if (!window.confirm(message)) { - return; - } - - addRunningActions(["fileTreeView-delete"]); - addInvalidNodes(...uids); - await callFileApi( - { - projectContext: project.context, - action: "remove", - fileTree, - fileHandlers, - uids, - }, - () => { - LogAllow && console.error("error while removing file system"); - reloadCurrentProject(); - }, - (allDone: boolean) => { - LogAllow && - console.log( - allDone ? "all is successfully removed" : "some is not removed", - ); - const action: TFileAction = { - action: "remove", - payload: { uids }, - }; - reloadCurrentProject(action); - }, - ); - removeInvalidNodes(...uids); - removeRunningActions(["fileTreeView-delete"]); - }, [ - selectedItems, - invalidNodes, - addRunningActions, - removeRunningActions, - addInvalidNodes, - removeInvalidNodes, - project, - fileTree, - fileHandlers, - reloadCurrentProject, - ]); - const cb_moveNode = useCallback( async (uids: string[], targetUid: TNodeUid, copy: boolean = false) => { // validate @@ -478,7 +478,7 @@ export const useNodeActionsHandler = ({ let allDone = true; await Promise.all( uids.map(async (uid) => { - const result = await duplicateNode( + /* const result = await duplicateNode( uid, true, fileTree, @@ -492,7 +492,7 @@ export const useNodeActionsHandler = ({ _targetUids.push(fileTree[uid].parentUid as TNodeUid); } else { allDone = false; - } + } */ }), ); @@ -574,14 +574,15 @@ export const useNodeActionsHandler = ({ ); return { + onDelete, + createFFNode, - createTmpFFNode, + createTmpNode, cb_startRenamingNode, cb_abortRenamingNode, cb_renameNode, onRename, onCut, - onDelete, cb_moveNode, cb_duplicateNode, cb_readNode, diff --git a/src/components/main/actionsPanel/workspaceTreeView/index.ts b/src/components/main/actionsPanel/workspaceTreeView/index.ts index d338bc96..e3c9de2a 100644 --- a/src/components/main/actionsPanel/workspaceTreeView/index.ts +++ b/src/components/main/actionsPanel/workspaceTreeView/index.ts @@ -1,5 +1,3 @@ import WorkspaceTreeView from "./WorkspaceTreeView"; export default WorkspaceTreeView; - -export * from "./errors"; diff --git a/src/components/main/actionsPanel/workspaceTreeView/workSpaceTreeComponents/Container.tsx b/src/components/main/actionsPanel/workspaceTreeView/workSpaceTreeComponents/Container.tsx deleted file mode 100644 index d39ab42b..00000000 --- a/src/components/main/actionsPanel/workspaceTreeView/workSpaceTreeComponents/Container.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import React, { FC } from "react"; - -interface ContainerProps { - children: React.ReactNode; - containerProps: React.HTMLProps; -} - -export const Container: FC = React.memo( - ({ containerProps, children }) => { - return
    {children}
; - }, -); diff --git a/src/components/main/actionsPanel/workspaceTreeView/workSpaceTreeComponents/ItemArrow.tsx b/src/components/main/actionsPanel/workspaceTreeView/workSpaceTreeComponents/ItemArrow.tsx deleted file mode 100644 index 33cbce08..00000000 --- a/src/components/main/actionsPanel/workspaceTreeView/workSpaceTreeComponents/ItemArrow.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import React, { FC } from "react"; - -import { TreeItem, TreeItemRenderContext } from "react-complex-tree"; - -import { SVGIconI, SVGIconII } from "@_components/common"; - -interface ItemArrowProps { - item: TreeItem; - context: TreeItemRenderContext; -} - -export const ItemArrow: FC = React.memo(({ item, context }) => { - return ( - <> - {item.isFolder ? ( - context.isExpanded ? ( - down - ) : ( - right - ) - ) : ( -
- )} - - ); -}); diff --git a/src/components/main/actionsPanel/workspaceTreeView/workSpaceTreeComponents/index.ts b/src/components/main/actionsPanel/workspaceTreeView/workSpaceTreeComponents/index.ts deleted file mode 100644 index 642bc0f5..00000000 --- a/src/components/main/actionsPanel/workspaceTreeView/workSpaceTreeComponents/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./Container"; -export * from "./ItemArrow"; diff --git a/src/pages/main/MainPage.tsx b/src/pages/main/MainPage.tsx index e801f683..9032850c 100644 --- a/src/pages/main/MainPage.tsx +++ b/src/pages/main/MainPage.tsx @@ -105,6 +105,7 @@ export default function MainPage() { htmlReferenceData, }); const { importProject, closeNavigator, reloadCurrentProject } = useHandlers({ + currentProjectFileHandle, setCurrentProjectFileHandle, setFileHandlers, diff --git a/src/pages/main/hooks/useCmdk.ts b/src/pages/main/hooks/useCmdk.ts index bfc5b6fb..0488b306 100644 --- a/src/pages/main/hooks/useCmdk.ts +++ b/src/pages/main/hooks/useCmdk.ts @@ -307,6 +307,7 @@ export const useCmdk = ({ cmdkReferenceData, importProject }: IUseCmdk) => { }, [KeyDownEventListener]); useEffect(() => { if (!currentCommand) return; + switch (currentCommand.action) { case "Jumpstart": onJumpstart(); diff --git a/src/pages/main/hooks/useFileHandlers.ts b/src/pages/main/hooks/useFileHandlers.ts index da9ece86..01074e45 100644 --- a/src/pages/main/hooks/useFileHandlers.ts +++ b/src/pages/main/hooks/useFileHandlers.ts @@ -1,4 +1,4 @@ -import { useState } from "react"; +import { useEffect, useState } from "react"; import { TFileHandlerCollection } from "@_node/index"; diff --git a/src/pages/main/hooks/useHandlers.ts b/src/pages/main/hooks/useHandlers.ts index c4110c87..3d655fed 100644 --- a/src/pages/main/hooks/useHandlers.ts +++ b/src/pages/main/hooks/useHandlers.ts @@ -1,4 +1,5 @@ -import { useCallback, useContext } from "react"; +import { useCallback } from "react"; + import { setMany } from "idb-keyval"; import { useDispatch } from "react-redux"; @@ -13,14 +14,13 @@ import { import { setCurrentFileUid, setDoingFileAction, - setFileAction, setFileTree, setInitialFileUidToOpen, setProject, - TFileAction, TProjectContext, updateFileTreeViewState, } from "@_redux/main/fileTree"; +import { setCurrentFileContent } from "@_redux/main/nodeTree"; import { setNavigatorDropdownType, setShowActionsPanel, @@ -28,10 +28,9 @@ import { import { useAppState } from "@_redux/useAppState"; import { clearProjectSession } from "../helper"; -import { MainContext } from "@_redux/main"; -import { setCurrentFileContent } from "@_redux/main/nodeTree"; interface IUseHandlers { + currentProjectFileHandle: FileSystemDirectoryHandle | null; setCurrentProjectFileHandle: React.Dispatch< React.SetStateAction >; @@ -49,6 +48,7 @@ interface IUseHandlers { >; } export const useHandlers = ({ + currentProjectFileHandle, setCurrentProjectFileHandle, setFileHandlers, @@ -62,7 +62,6 @@ export const useHandlers = ({ const dispatch = useDispatch(); const { osType, navigatorDropdownType, project, fileTree, currentFileUid } = useAppState(); - const { currentProjectFileHandle } = useContext(MainContext); const saveRecentProject = useCallback( async ( @@ -188,71 +187,66 @@ export const useHandlers = ({ }, [osType, saveRecentProject], ); - const reloadCurrentProject = useCallback( - async (action?: TFileAction) => { - if (project.context === "local") { - const { - handlerArr, - _fileHandlers, - _fileTree, - _initialFileUidToOpen, - deletedUidsObj, - deletedUids, - } = await loadLocalProject( - currentProjectFileHandle as FileSystemDirectoryHandle, - osType, - true, - fileTree, - ); - dispatch(setFileTree(_fileTree)); - setFileHandlers(_fileHandlers); - // need to open another file if the current open file is deleted - if (deletedUidsObj[currentFileUid]) { + const reloadCurrentProject = useCallback(async () => { + if (project.context === "local") { + const { + handlerArr, + _fileHandlers, + _fileTree, + _initialFileUidToOpen, + deletedUidsObj, + deletedUids, + } = await loadLocalProject( + currentProjectFileHandle as FileSystemDirectoryHandle, + osType, + true, + fileTree, + ); + dispatch(setFileTree(_fileTree)); + setFileHandlers(_fileHandlers); + // need to open another file if the current open file is deleted + if (deletedUidsObj[currentFileUid]) { + if (!!_initialFileUidToOpen) { dispatch(setCurrentFileUid(_initialFileUidToOpen)); dispatch( setCurrentFileContent( _fileTree[_initialFileUidToOpen].data.content, ), ); + } else { + dispatch(setCurrentFileUid("")); + dispatch(setCurrentFileContent("")); } - // update file tree view state - dispatch(updateFileTreeViewState({ deletedUids: deletedUids })); - // build nohost idb - buildNohostIDB( - handlerArr, - deletedUids.map((uid) => fileTree[uid].data.path), - ); - } else { - const { - _fileTree, - _initialFileUidToOpen, - deletedUidsObj, - deletedUids, - } = await loadIDBProject(DefaultProjectPath, true, fileTree); - dispatch(setFileTree(_fileTree)); - // need to open another file if the current open file is deleted - if (deletedUidsObj[currentFileUid]) { + } + // update file tree view state + dispatch(updateFileTreeViewState({ deletedUids: deletedUids })); + // build nohost idb + buildNohostIDB( + handlerArr, + deletedUids.map((uid) => fileTree[uid].data.path), + ); + } else { + const { _fileTree, _initialFileUidToOpen, deletedUidsObj, deletedUids } = + await loadIDBProject(DefaultProjectPath, true, fileTree); + dispatch(setFileTree(_fileTree)); + // need to open another file if the current open file is deleted + if (deletedUidsObj[currentFileUid]) { + if (!!_initialFileUidToOpen) { dispatch(setCurrentFileUid(_initialFileUidToOpen)); dispatch( setCurrentFileContent( _fileTree[_initialFileUidToOpen].data.content, ), ); + } else { + dispatch(setCurrentFileUid("")); + dispatch(setCurrentFileContent("")); } - // update file tree view state - dispatch(updateFileTreeViewState({ deletedUids: deletedUids })); - // update nohost idb - buildNohostIDB( - [], - deletedUids.map((uid) => fileTree[uid].data.path), - ); } - - // add fileAction to event history - action && dispatch(setFileAction(action)); - }, - [project, osType, fileTree, currentFileUid], - ); + // update file tree view state + dispatch(updateFileTreeViewState({ deletedUids: deletedUids })); + } + }, [project, osType, fileTree, currentFileUid]); const closeNavigator = useCallback(() => { navigatorDropdownType !== null && dispatch(setNavigatorDropdownType(null)); }, [navigatorDropdownType]);