diff --git a/src/_node/file/actions.ts b/src/_node/file/actions.ts index 1fd0f5a6..e70400d9 100644 --- a/src/_node/file/actions.ts +++ b/src/_node/file/actions.ts @@ -3,11 +3,20 @@ import { LogAllow } from "@_constants/global"; import { TFileApiPayload, TFileHandlerCollection, + TFileNodeData, TFileNodeTreeData, + TNodeTreeData, TNodeUid, + moveIDBFF, + moveLocalFF, } from "../"; import { TProjectContext } 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 ({ @@ -40,10 +49,142 @@ const remove = async ({ } }); }; -const cut = () => {}; -const copy = () => {}; -const duplicate = () => {}; -const move = () => {}; + +const move = async ({ + projectContext, + fileHandlers, + uids, + clipboardData, + fileTree, + targetNode, +}: { + projectContext: TProjectContext; + fileHandlers: any; + uids: string[]; + clipboardData: TClipboardData | null; + fileTree: TFileNodeTreeData; + targetNode: any; +}) => { + return new Promise((resolve, reject) => { + uids.map(async (uid) => { + const node = fileTree[uid]; + if (node === undefined) { + return false; + } + + const nodeData = node.data as TFileNodeData; + const parentNode = fileTree[node.parentUid as TNodeUid]; + if (parentNode === undefined) { + return false; + } + + const handler = fileHandlers[uid]; + + const parentHandler = fileHandlers[ + parentNode.uid + ] as FileSystemDirectoryHandle; + let targetHandler = null; + + if (targetNode.data.kind === "file") { + targetHandler = fileHandlers[ + targetNode.parentUid + ] as FileSystemDirectoryHandle; + } else { + targetHandler = fileHandlers[ + targetNode.uid + ] as FileSystemDirectoryHandle; + } + if ( + !(await verifyFileHandlerPermission(handler)) || + !(await verifyFileHandlerPermission(parentHandler)) || + !(await verifyFileHandlerPermission(targetHandler)) + ) { + return false; + } + const newFileName = await generateNewNameMoveNode( + nodeData, + targetHandler, + ); + + // move + try { + if (projectContext === "local") { + await moveLocalFF( + handler, + parentHandler, + targetHandler, + newFileName, + clipboardData?.type === "copy", + ); + } else if (projectContext === "idb") { + const targetNodeData = fileTree[targetNode.uid].data as TFileNodeData; + await moveIDBFF( + nodeData, + targetNodeData, + newFileName, + clipboardData?.type === "copy", + ); + } + resolve(true); + } catch (err) { + reject(err); + } + }); + }); +}; + +const cut = ({ + dispatch, + uids, + fileTree, + currentFileUid, + nodeTree, +}: { + dispatch: Dispatch; + uids: TNodeUid[]; + fileTree: TFileNodeTreeData; + currentFileUid: string; + nodeTree: TNodeTreeData; +}) => { + dispatch( + setClipboardData({ + panel: "file", + type: "cut", + uids, + fileType: fileTree[currentFileUid].data.type, + data: [], + fileUid: currentFileUid, + prevNodeTree: nodeTree, + }), + ); +}; + +const copy = ({ + dispatch, + uids, + fileTree, + currentFileUid, + nodeTree, +}: { + dispatch: Dispatch; + uids: TNodeUid[]; + fileTree: TFileNodeTreeData; + currentFileUid: string; + nodeTree: TNodeTreeData; +}) => { + dispatch( + setClipboardData({ + panel: "file", + type: "copy", + uids, + fileType: fileTree[currentFileUid].data.type, + data: [], + fileUid: currentFileUid, + prevNodeTree: nodeTree, + }), + ); +}; + const rename = () => {}; export const doFileActions = async ( @@ -58,7 +199,11 @@ export const doFileActions = async ( uids, fileTree, fileHandlers, - osType = "Windows", + dispatch, + currentFileUid, + nodeTree, + clipboardData, + targetNode, } = params; let allDone = true; @@ -75,16 +220,27 @@ export const doFileActions = async ( }); break; case "cut": - cut(); + cut({ + dispatch, + uids, + fileTree, + currentFileUid, + nodeTree, + }); break; case "copy": - copy(); - break; - case "duplicate": - duplicate(); + copy({ dispatch, uids, fileTree, currentFileUid, nodeTree }); break; + case "move": - move(); + allDone = await move({ + projectContext, + fileHandlers, + uids, + clipboardData, + fileTree, + targetNode, + }); break; case "rename": rename(); diff --git a/src/_node/file/helpers.ts b/src/_node/file/helpers.ts index f9587120..cca7ed63 100644 --- a/src/_node/file/helpers.ts +++ b/src/_node/file/helpers.ts @@ -5,8 +5,16 @@ import { TFileNodeData, TFileNodeTreeData, TNodeUid, + _getIDBDirectoryOrFileStat, _path, + _readIDBFile, + _removeIDBDirectoryOrFile, + _writeIDBFile, } from "../"; +import { + copyDirectory, + moveDirectory, +} from "@_components/main/actionsPanel/workspaceTreeView/helpers"; export const sortFilesByASC = (handlerObj: TFileHandlerInfoObj) => { // sort by ASC directory/file @@ -85,3 +93,172 @@ export const getNormalizedPath = ( const normalizedPath = _path.normalize(path); return { isAbsolutePath, normalizedPath }; }; + +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"; + } + } +}; diff --git a/src/_node/file/types.ts b/src/_node/file/types.ts index 0b09e071..f07bfef2 100644 --- a/src/_node/file/types.ts +++ b/src/_node/file/types.ts @@ -10,6 +10,9 @@ import { TNodeUid, } from "../"; import { TFileActionType, TProjectContext } from "@_redux/main/fileTree"; +import { AnyAction } from "@reduxjs/toolkit"; +import { Dispatch } from "react"; +import { TClipboardData } from "@_redux/main/processor"; export type TFileNode = TNode & { data: TFileNodeData; @@ -79,8 +82,52 @@ export type TFileApiPayloadBase = { }; export type TFileApiPayload = TFileApiPayloadBase & ( - | { action: Extract; uids: TNodeUid[] } - | { action: Exclude; uids?: never } + | { + action: Extract; + uids: TNodeUid[]; + } + | { + action: Exclude; + uids?: never; + } + ) & + ( + | { + action: Extract; + currentFileUid: string; + } + | { + action: Exclude; + currentFileUid?: never; + } + ) & + ( + | { + action: Extract; + nodeTree: TNodeTreeData; + } + | { action: Exclude; nodeTree?: never } + ) & + ( + | { + action: Extract; + dispatch: Dispatch; + } + | { action: Exclude; dispatch?: never } + ) & + ( + | { + action: Extract; + clipboardData: TClipboardData | null; + } + | { action: Exclude; clipboardData?: never } + ) & + ( + | { + action: Extract; + targetNode: TFileNode; + } + | { action: Exclude; targetNode?: never } ); export type TZipFileInfo = { diff --git a/src/components/main/actionsPanel/workspaceTreeView/helpers/duplicateNode.ts b/src/components/main/actionsPanel/workspaceTreeView/helpers/duplicateNode.ts index 92cb98db..6cd305f9 100644 --- a/src/components/main/actionsPanel/workspaceTreeView/helpers/duplicateNode.ts +++ b/src/components/main/actionsPanel/workspaceTreeView/helpers/duplicateNode.ts @@ -1,11 +1,14 @@ -import { TFileHandlerCollection, TFileNodeData } from "@_node/file"; +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 "./"; -import { moveActions } from "./moveActions"; export const duplicateNode = async ( uid: TNodeUid, @@ -16,8 +19,6 @@ export const duplicateNode = async ( addInvalidNodes: any, invalidNodes: { [uid: string]: boolean }, ) => { - const { moveLocalFF } = moveActions(addMessage); - const node = ffTree[uid]; if (!node) return; diff --git a/src/components/main/actionsPanel/workspaceTreeView/helpers/generateNewNameMoveNode.ts b/src/components/main/actionsPanel/workspaceTreeView/helpers/generateNewNameMoveNode.ts index d862c158..57ee7162 100644 --- a/src/components/main/actionsPanel/workspaceTreeView/helpers/generateNewNameMoveNode.ts +++ b/src/components/main/actionsPanel/workspaceTreeView/helpers/generateNewNameMoveNode.ts @@ -3,17 +3,26 @@ import { TFileNodeData } from "@_node/file"; export const generateNewNameMoveNode = async ( nodeData: TFileNodeData, targetHandler: FileSystemDirectoryHandle, - copy: boolean, ) => { let newName = nodeData.kind === "directory" ? nodeData.name - : `${nodeData.name}${nodeData.ext}`; - if (copy) { - if (nodeData.kind === "directory") { - let folderName = nodeData.name; - let exists = false; + : `${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, }); @@ -22,35 +31,35 @@ export const generateNewNameMoveNode = async ( 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; - } + 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; + } + 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, }); @@ -59,32 +68,22 @@ export const generateNewNameMoveNode = async ( 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; - } + 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; } + newName = fileName; } } + return newName; }; diff --git a/src/components/main/actionsPanel/workspaceTreeView/helpers/index.ts b/src/components/main/actionsPanel/workspaceTreeView/helpers/index.ts index c88c8b73..55ead0df 100644 --- a/src/components/main/actionsPanel/workspaceTreeView/helpers/index.ts +++ b/src/components/main/actionsPanel/workspaceTreeView/helpers/index.ts @@ -1,12 +1,9 @@ -export * from "./moveActions"; export * from "./copyDirectory"; -export * from "./moveFile"; export * from "./moveDirectory"; export * from "./createFileOrFolder"; export * from "./deleteFileOrFolder"; export * from "./generateNewName"; export * from "./renameNode"; -export * from "./validateAndMoveNode"; export * from "./generateNewNameMoveNode"; export * from "./duplicateNode"; export * from "./generateNewNodeName"; diff --git a/src/components/main/actionsPanel/workspaceTreeView/helpers/moveActions.ts b/src/components/main/actionsPanel/workspaceTreeView/helpers/moveActions.ts deleted file mode 100644 index 1224f7c2..00000000 --- a/src/components/main/actionsPanel/workspaceTreeView/helpers/moveActions.ts +++ /dev/null @@ -1,142 +0,0 @@ -import { - _getIDBDirectoryOrFileStat, - _readIDBFile, - _removeIDBDirectoryOrFile, - TFileNodeData, - _writeIDBFile, -} from "@_node/file"; -import { TToast } from "@_types/global"; - -import { copyDirectory, moveDirectory, moveFile } from "./"; - -export const moveActions = (addMessage: (message: TToast) => void) => { - 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, - ); - } - }; - - const moveIDBFF = async ( - nodeData: TFileNodeData, - targetNodeData: TFileNodeData, - newName: string, - copy: boolean = false, - showWarning: 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"; - } - } - }; - - return { - moveLocalFF, - moveIDBFF, - }; -}; diff --git a/src/components/main/actionsPanel/workspaceTreeView/helpers/moveFile.ts b/src/components/main/actionsPanel/workspaceTreeView/helpers/moveFile.ts deleted file mode 100644 index 116e113b..00000000 --- a/src/components/main/actionsPanel/workspaceTreeView/helpers/moveFile.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { TToast } from "@_types/global"; - -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 - let exists = true; - try { - await targetHandler.getFileHandle(newName, { create: false }); - 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 { - 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"); - } -}; diff --git a/src/components/main/actionsPanel/workspaceTreeView/helpers/renameNode.ts b/src/components/main/actionsPanel/workspaceTreeView/helpers/renameNode.ts index c4d3fa14..abdeefe4 100644 --- a/src/components/main/actionsPanel/workspaceTreeView/helpers/renameNode.ts +++ b/src/components/main/actionsPanel/workspaceTreeView/helpers/renameNode.ts @@ -2,7 +2,7 @@ import { useContext } from "react"; import { useDispatch } from "react-redux"; -import { TFileNodeData } from "@_node/file"; +import { TFileNodeData, moveIDBFF, moveLocalFF } from "@_node/file"; import { TNode, TNodeUid } from "@_node/types"; import { MainContext } from "@_redux/main"; import { @@ -14,7 +14,6 @@ import { useAppState } from "@_redux/useAppState"; import { verifyFileHandlerPermission } from "@_services/main"; import { useInvalidNodes } from "../hooks"; -import { moveActions } from "./moveActions"; export const renameNode = async ( ext: string, @@ -32,8 +31,6 @@ export const renameNode = async ( const { removeInvalidNodes, addInvalidNodes } = useInvalidNodes(); - const { moveIDBFF, moveLocalFF } = moveActions(() => {}); - const _orgName = ext === "*folder" ? `${nodeData.name}` : `${nodeData.name}${nodeData.ext}`; @@ -77,7 +74,7 @@ export const renameNode = async ( addInvalidNodes(newUid); try { - await moveIDBFF(nodeData, parentNodeData, _newName, false, true); + await moveIDBFF(nodeData, parentNodeData, _newName, false); removeInvalidNodes(newUid); } catch (err) { // addMessage(renamingError); diff --git a/src/components/main/actionsPanel/workspaceTreeView/helpers/validateAndMoveNode.ts b/src/components/main/actionsPanel/workspaceTreeView/helpers/validateAndMoveNode.ts deleted file mode 100644 index 7aa4a24e..00000000 --- a/src/components/main/actionsPanel/workspaceTreeView/helpers/validateAndMoveNode.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { useContext } from "react"; - -import { TFileNodeData } from "@_node/file"; -import { TNodeUid } from "@_node/types"; -import { MainContext } from "@_redux/main"; -import { useAppState } from "@_redux/useAppState"; -import { verifyFileHandlerPermission } from "@_services/main"; - -import { useInvalidNodes } from "../hooks"; -import { generateNewNameMoveNode } from "./generateNewNameMoveNode"; -import { moveActions } from "./moveActions"; - -export const validateAndMoveNode = async ( - uid: string, - targetUid: TNodeUid, - copy: boolean = false, -) => { - const { project, fileTree } = useAppState(); - - const { fileHandlers } = useContext(MainContext); - - const { addInvalidNodes }: any = useInvalidNodes(); - - const { moveIDBFF, moveLocalFF } = moveActions(() => {}); - - const node = fileTree[uid]; - - if (node === undefined) { - return false; - } - - const nodeData = node.data as TFileNodeData; - const parentNode = fileTree[node.parentUid as TNodeUid]; - - if (parentNode === undefined) { - return false; - } - - const handler = fileHandlers[uid]; - const parentHandler = fileHandlers[ - parentNode.uid - ] as FileSystemDirectoryHandle; - - if ( - !(await verifyFileHandlerPermission(handler)) || - !(await verifyFileHandlerPermission(parentHandler)) - ) { - return false; - } - - const newUid = `${targetUid}/${await generateNewNameMoveNode( - nodeData, - parentHandler, - copy, - )}`; - - // update invalidNodes - addInvalidNodes((prevState: Record) => ({ - ...prevState, - [uid]: true, - [newUid]: true, - })); - - // move - try { - if (project.context === "local") { - await moveLocalFF(handler, parentHandler, parentHandler, newUid, copy); - } else if (project.context === "idb") { - const targetNode = fileTree[targetUid]; - const targetNodeData = targetNode.data as TFileNodeData; - await moveIDBFF(nodeData, targetNodeData, newUid, copy); - } - return true; - } catch (err) { - return false; - } finally { - // update invalidNodes - addInvalidNodes((prevState: Record) => { - delete prevState[uid]; - delete prevState[newUid]; - return { ...prevState }; - }); - } -}; diff --git a/src/components/main/actionsPanel/workspaceTreeView/hooks/useCmdk.ts b/src/components/main/actionsPanel/workspaceTreeView/hooks/useCmdk.ts index 50567ffb..129302a2 100644 --- a/src/components/main/actionsPanel/workspaceTreeView/hooks/useCmdk.ts +++ b/src/components/main/actionsPanel/workspaceTreeView/hooks/useCmdk.ts @@ -1,4 +1,4 @@ -import { useCallback, useEffect } from "react"; +import { useCallback, useContext, useEffect } from "react"; import { useDispatch } from "react-redux"; @@ -9,6 +9,9 @@ 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: { @@ -44,16 +47,17 @@ export const useCmdk = ({ currentCommand, } = useAppState(); - const { createTmpFFNode, cb_deleteNode, cb_moveNode, cb_duplicateNode } = - useNodeActionsHandler({ - invalidNodes, - addInvalidNodes, - removeInvalidNodes, - temporaryNodes, - addTemporaryNodes, - removeTemporaryNodes, - openFileUid, - }); + const { fileHandlers, reloadCurrentProject, currentProjectFileHandle } = + useContext(MainContext); + const { createTmpFFNode } = useNodeActionsHandler({ + invalidNodes, + addInvalidNodes, + removeInvalidNodes, + temporaryNodes, + addTemporaryNodes, + removeTemporaryNodes, + openFileUid, + }); const onAddNode = useCallback( (actionName: string) => { @@ -64,34 +68,19 @@ export const useCmdk = ({ }, [createTmpFFNode], ); - const onDelete = useCallback(() => { - cb_deleteNode(); - }, [cb_deleteNode]); - - const onCut = useCallback(() => { - dispatch( - setClipboardData({ - panel: "file", - type: "cut", - uids: selectedItems, - fileType: fileTree[currentFileUid].data.type, - data: [], - fileUid: currentFileUid, - prevNodeTree: nodeTree, - }), - ); - }, [selectedItems, fileTree[currentFileUid], nodeTree]); const onCopy = useCallback(() => { - setClipboardData({ - panel: "file", - type: "copy", + const params: TFileApiPayload = { + projectContext: "local", + action: "copy", uids: selectedItems, - fileType: fileTree[currentFileUid].data.type, - data: [], - fileUid: currentFileUid, - prevNodeTree: nodeTree, - }); + fileTree, + fileHandlers, + dispatch, + currentFileUid, + nodeTree, + }; + doFileActions(params); }, [selectedItems, fileTree[currentFileUid], nodeTree]); const onPaste = useCallback(() => { @@ -101,26 +90,71 @@ export const useCmdk = ({ if (invalidNodes[focusedItem]) return; const uids = clipboardData.uids.filter((uid) => !invalidNodes[uid]); if (uids.length === 0) return; - - if (clipboardData.type === "cut") { - setClipboardData({ - panel: "file", - type: "cut", - uids: [], - fileType: "html", - data: [], - fileUid: "", - prevNodeTree: {}, - }); - cb_moveNode(uids, focusedItem); - } else if (clipboardData.type === "copy") { - cb_moveNode(uids, focusedItem, true); - } - }, [clipboardData, invalidNodes, focusedItem, cb_moveNode]); + 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(fileTree, currentProjectFileHandle); + LogAllow && + console.log( + allDone ? "all is successfully removed" : "some is not removed", + ); + }, + ); + }, [clipboardData, selectedItems, fileTree[currentFileUid], nodeTree]); const onDuplicate = useCallback(() => { - cb_duplicateNode(); - }, [cb_duplicateNode]); + 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(fileTree, currentProjectFileHandle); + 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; diff --git a/src/components/main/actionsPanel/workspaceTreeView/hooks/useFileOperations.ts b/src/components/main/actionsPanel/workspaceTreeView/hooks/useFileOperations.ts index 4d137994..d1f8e783 100644 --- a/src/components/main/actionsPanel/workspaceTreeView/hooks/useFileOperations.ts +++ b/src/components/main/actionsPanel/workspaceTreeView/hooks/useFileOperations.ts @@ -1,17 +1,13 @@ import { useCallback, useContext } from "react"; -import { TFileNodeData } from "@_node/file"; +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, - moveActions, -} from "../helpers"; +import { createFileOrFolder, deleteFileOrFolder } from "../helpers"; import { LogAllow } from "@_constants/global"; interface IUseFileOperations { @@ -38,8 +34,6 @@ export const useFileOperations = ({ const { addRunningActions, removeRunningActions, fileHandlers } = useContext(MainContext); - const { moveIDBFF, moveLocalFF } = moveActions(() => {}); - const _create = useCallback( async (params: { parentUid: TNodeUid; diff --git a/src/components/main/actionsPanel/workspaceTreeView/hooks/useNodeActionsHandler.ts b/src/components/main/actionsPanel/workspaceTreeView/hooks/useNodeActionsHandler.ts index 6db9f00e..c821b9eb 100644 --- a/src/components/main/actionsPanel/workspaceTreeView/hooks/useNodeActionsHandler.ts +++ b/src/components/main/actionsPanel/workspaceTreeView/hooks/useNodeActionsHandler.ts @@ -14,7 +14,6 @@ import { TFileNodeData, _writeIDBFile, confirmAlert, - loadLocalProject, } from "@_node/file"; import { getValidNodeUids } from "@_node/helpers"; import { TNode, TNodeTreeData, TNodeUid } from "@_node/types"; @@ -36,12 +35,7 @@ import { useAppState } from "@_redux/useAppState"; import { verifyFileHandlerPermission } from "@_services/main"; import { TFileNodeType } from "@_types/main"; -import { - duplicateNode, - generateNewName, - renameNode, - validateAndMoveNode, -} from "../helpers"; +import { duplicateNode, generateNewName, renameNode } from "../helpers"; import { callFileApi } from "@_node/apis"; import { LogAllow } from "@_constants/global"; @@ -77,6 +71,8 @@ export const useNodeActionsHandler = ({ fFocusedItem: focusedItem, fExpandedItemsObj: expandedItemsObj, fSelectedItems: selectedItems, + nodeTree, + clipboardData, } = useAppState(); const { addRunningActions, @@ -303,8 +299,27 @@ export const useNodeActionsHandler = ({ removeInvalidNodes, ], ); + const onCut = useCallback(async () => { + const uids = selectedItems.filter((uid) => !invalidNodes[uid]); + if (uids.length === 0) return; - const cb_deleteNode = useCallback(async () => { + await callFileApi( + { + projectContext: project.context, + dispatch, + action: "cut", + fileTree, + currentFileUid, + uids, + nodeTree, + }, + () => { + LogAllow && console.error("error while cutting file system"); + }, + ); + }, [selectedItems, fileTree[currentFileUid], nodeTree]); + + const onDelete = useCallback(async () => { const uids = selectedItems.filter((uid) => !invalidNodes[uid]); if (uids.length === 0) return; @@ -349,46 +364,56 @@ export const useNodeActionsHandler = ({ ]); const cb_moveNode = useCallback( - async (uids: TNodeUid[], targetUid: TNodeUid, copy: boolean = false) => { + async (uids: string[], targetUid: TNodeUid, copy: boolean = false) => { // validate const targetNode = fileTree[targetUid]; - if (targetNode === undefined) { return; } - const validatedUids = getValidNodeUids(fileTree, uids, targetUid); - if (validatedUids.length === 0) { return; } - - // confirm files' changes + // confirm files changes const hasChangedFile = validatedUids.some((uid) => { const _file = fileTree[uid]; const _fileData = _file.data as TFileNodeData; return _file && _fileData.changed; }); - if (hasChangedFile && !confirmAlert(FileChangeAlertMessage)) return; - addRunningActions(["fileTreeView-move"]); - - const _uids = await Promise.all( - validatedUids.map((uid) => validateAndMoveNode(uid, targetUid, copy)), + addInvalidNodes(...validatedUids); + await callFileApi( + { + projectContext: project.context, + action: "move", + fileHandlers, + uids, + fileTree, + targetNode, + clipboardData, + }, + () => { + LogAllow && console.error("error while pasting file system"); + }, + (allDone: boolean) => { + reloadCurrentProject(fileTree, currentProjectFileHandle); + LogAllow && + console.log( + allDone ? "all is successfully past" : "some is not past", + ); + }, ); - - if (_uids.some((result) => !result)) { - // addMessage(movingError); - } - + removeInvalidNodes(...validatedUids); + // if (_uids.some((result) => !result)) { + // // addMessage(movingError); + // } const action: TFileAction = { type: copy ? "copy" : "cut", - param1: _uids, - param2: _uids.map(() => targetUid), + // param1: _uids, + // param2: _uids.map(() => targetUid), }; dispatch(setFileAction(action)); - removeRunningActions(["fileTreeView-move"]); }, [ @@ -536,7 +561,8 @@ export const useNodeActionsHandler = ({ cb_abortRenamingNode, cb_renameNode, _cb_renameNode, - cb_deleteNode, + onCut, + onDelete, cb_moveNode, cb_duplicateNode, cb_readNode,