diff --git a/main.js b/main.js index eabaea7..cc5ccd9 100644 --- a/main.js +++ b/main.js @@ -2,11 +2,7 @@ const {app, Menu, BrowserWindow,ipcMain,dialog} = require('electron') const path = require('path') const {menuRebuild} = require('./src/comment/TopMenu.js') const Store = require('electron-store'); -const yaml = require('js-yaml'); - const store = new Store(); - - const createWindow = () => { // Create the browser window. const win = new BrowserWindow({ @@ -81,6 +77,7 @@ app.whenReady().then(() => { return store.delete(args) }) console.log("配置文件地址",app.getPath('userData')+"/config.json") + console.log("操作系统:"+process.platform) }) // 除了 macOS 外,当所有窗口都被关闭的时候退出程序。 因此, 通常 // 对应用程序和它们的菜单栏来说应该时刻保持激活状态, diff --git a/src/comment/TopMenu.js b/src/comment/TopMenu.js index 3ae3353..19046c4 100644 --- a/src/comment/TopMenu.js +++ b/src/comment/TopMenu.js @@ -1,5 +1,6 @@ const {app, Menu, shell, dialog} = require('electron') const {stat, readdir} = require("fs/promises"); +const pathOp = require('path') const isMac = process.platform === 'darwin' const readDirLocal=async (filePath) => { const files = await readdir(filePath); @@ -9,19 +10,19 @@ const readDirLocal=async (filePath) => { "fileName": filePath, "filePath": filePath, "dirFlag": true, - "childList": fileChildList + "children": fileChildList }) for (let i = 0; i < files.length; i++) { - const state = await stat(filePath + '/' + files[i]); + const state = await stat(filePath + pathOp.sep + files[i]); if (state.isDirectory() || files[i].endsWith(".md") || files[i].endsWith(".html") || files[i].endsWith(".lexical")) { fileChildList.push({ 'fileName': files[i], - "filePath": filePath + '/' + files[i], + "filePath": filePath + pathOp.sep + files[i], 'dirFlag': state.isDirectory(), - "childList":[] + "children":[] }) } } diff --git a/src/components/ActionPlug/index.jsx b/src/components/ActionPlug/index.jsx deleted file mode 100644 index 1db0d8a..0000000 --- a/src/components/ActionPlug/index.jsx +++ /dev/null @@ -1,25 +0,0 @@ -import {Button} from "antd"; -import {importFile} from "../../utils/File"; -import {useLexicalComposerContext} from '@lexical/react/LexicalComposerContext'; -export default function actionPlug(){ - const [editor] = useLexicalComposerContext(); - return -} \ No newline at end of file diff --git a/src/components/ItemTree/DirAddFile/index.jsx b/src/components/ItemTree/DirAddFile/index.jsx index fd766f2..df69c86 100644 --- a/src/components/ItemTree/DirAddFile/index.jsx +++ b/src/components/ItemTree/DirAddFile/index.jsx @@ -1,10 +1,11 @@ import React, {useRef, useState} from 'react'; import {Input, message, Modal} from 'antd'; -import {useDispatch} from "react-redux"; +import {useDispatch, useSelector} from "react-redux"; import {newFile} from "../../../utils/File"; import {dirFileAdd} from "../../../redux/dirMessage_reducer"; import {addTableBarItem} from "../../../redux/tableBarItem_reducer"; import {isEmpty} from "../../../utils/ObjectUtils"; +import {fileNameFormat} from "../../../utils/PathOperate"; const DirAddFile = (prop) => { console.log("prop",prop) @@ -27,7 +28,7 @@ const DirAddFile = (prop) => { return } // 新建文件 - let fileName = prop.filePath+"/"+inputValue.current.input.value+".lexical" + let fileName = fileNameFormat(prop.filePath,inputValue.current.input.value,".lexical") newFile(fileName) // 更新树 dispatch(dirFileAdd({"filePath":prop.filePath,fileName})) diff --git a/src/components/ItemTree/UpdateFileName/index.jsx b/src/components/ItemTree/UpdateFileName/index.jsx index 8088680..703e109 100644 --- a/src/components/ItemTree/UpdateFileName/index.jsx +++ b/src/components/ItemTree/UpdateFileName/index.jsx @@ -4,6 +4,7 @@ import {updateFileName} from "../../../utils/File"; import {useDispatch} from "react-redux"; import {updateFileName as updateFileNameRedux} from "../../../redux/dirMessage_reducer"; import {updateFileName as updateFileNameBar} from "../../../redux/tableBarItem_reducer"; +import {replaceFileNameByFilePath} from "../../../utils/PathOperate"; const UpdateFileName = (prop) => { console.log("prop",prop) @@ -16,13 +17,12 @@ const UpdateFileName = (prop) => { const handleOk = () => { setIsModalOpen(false); console.log("inputValue",inputValue.current.input.value) + // 修改文件名不修改文件扩展名 // 如果和原始名称一样,关闭菜单直接返回 // 如果不一样,修改文件名并且更新树,同步条目 if (prop.fileName!==inputValue.current.input.value){ - // 修改文件名 - let first = prop.filePath.lastIndexOf("/") - let second = prop.filePath.lastIndexOf(".") - let newFilePath= prop.filePath.substring(0,first+1)+inputValue.current.input.value+prop.filePath.substring(second) + // 修改文件名,新文件地址 + let newFilePath= replaceFileNameByFilePath(prop.filePath,inputValue.current.input.value) updateFileName(prop.filePath,newFilePath) // 更新树 dispatch(updateFileNameRedux({"oldFilePath":prop.filePath,"newFilePath":newFilePath})) diff --git a/src/components/ItemTree/index.jsx b/src/components/ItemTree/index.jsx index e3c9368..50d87b9 100644 --- a/src/components/ItemTree/index.jsx +++ b/src/components/ItemTree/index.jsx @@ -2,7 +2,7 @@ import React, {useEffect, useMemo, useState} from 'react'; import {Input, Menu, Tree} from 'antd'; import {FolderOutlined, FileMarkdownOutlined, FileOutlined, DeleteOutlined, RedoOutlined} from '@ant-design/icons'; import "./index.less" -import {getFileNameByPath} from "../../utils/File"; +import {getFileDirByPath, getFileFullNameByPath, getFileNameByPath} from "../../utils/PathOperate"; const {Search} = Input; import {useSelector, useDispatch} from "react-redux"; import {addExpandedKeys, addTableBarItem, setExpandedKeys} from "../../redux/tableBarItem_reducer"; @@ -50,23 +50,23 @@ const getParentKey = (key, tree) => { function generateChildList(fileList) { const result = [] for (let i = 0; i < fileList.length; i++) { - const {fileName, filePath, dirFlag, childList} = fileList[i]; - const childListM = [] - if (Array.isArray(childList) && childList.length > 0) { - childListM.push(...generateChildList(childList)); + const {fileName, filePath, dirFlag, children} = fileList[i]; + const childrenM = [] + if (Array.isArray(children) && children.length > 0) { + childrenM.push(...generateChildList(children)); } result.push({ "key": filePath, - "title": titleExtended(fileName, dirFlag, filePath), + "title": titleExtended(fileName, filePath), "icon": dirFlag ? : fileName.endsWith(".md") ? : , "dirFlag": dirFlag, - "children": childListM + "children": childrenM }); } return result; } -const titleExtended = (fileName, dirFlag, filePath) => { +const titleExtended = (fileName, filePath) => { return {fileName} } /** @@ -80,18 +80,18 @@ const flushTree = (fileDirDate) => { for (let i = 0; i < fileDirDate.length; i++) { const node = fileDirDate[i]; console.log("node:", node) - const {fileName, filePath, childList, dirFlag} = node; - const childListM = [] - if (Array.isArray(childList) && childList.length > 0) { - childListM.push(...generateChildList(childList)); + const {fileName, filePath, children, dirFlag} = node; + const childrenM = [] + if (Array.isArray(children) && children.length > 0) { + childrenM.push(...generateChildList(children)); } defaultValueStateSet.push({ "key": filePath, // 修改属性后此处也需要修改 - "title": titleExtended(getFileNameByPath(fileName), dirFlag, filePath), + "title": titleExtended(getFileNameByPath(fileName), filePath), "icon": , "dirFlag": dirFlag, - "children": childListM + "children": childrenM }); } @@ -127,6 +127,36 @@ const ItemTree = (prop) => { } }) } + const itemTreeAddFile = (dirMessage)=>{ + setDefaultValueState(flushTree(dirMessage)) + // return + // let newFile = { + // "fileName": getFileFullNameByPath(filePath), + // "filePath": filePath, + // "dirFlag": false, + // "children": [] + // } + // // 查找对应的目录并添加信息 + // let fileDir = getFileDirByPath(filePath) + // let updateValueState = [...prop.filePath] + // updateValueState.forEach(file=>{ + // if (fileDir===file.filePath && file.dirFlag){ + // file.children=[...file.children,newFile] + // } else if (fileDir.startsWith(file.filePath) && file.dirFlag ){ + // treeItemChildAddFile(file.children,newFile,fileDir) + // } + // }) + // setDefaultValueState(flushTree(updateValueState)) + } + function treeItemChildAddFile(treeItemList,newFile,fileDir){ + treeItemList.forEach(file=>{ + if (fileDir===file.filePath && file.dirFlag){ + file.children=[...file.children,newFile] + } else if (fileDir.startsWith(file.filePath) && file.dirFlag){ + treeItemChildAddFile(file.children,newFile,fileDir) + } + }) + } const onChange = (e) => { const {value} = e.target; @@ -145,7 +175,7 @@ const ItemTree = (prop) => { const refreshDir = (filePath) => { readDir(filePath).then(fileStateList => { - if (Array.isArray(fileStateList[0].childList) && fileStateList[0].childList.length > 0) { + if (Array.isArray(fileStateList[0].children) && fileStateList[0].children.length > 0) { dispatch(refreshDirReducer({selectDirKey: filePath, fileStateList})) // 添加下级节点 addChildNode(defaultValueState, flushTree(fileStateList)) @@ -165,7 +195,7 @@ const ItemTree = (prop) => { // 加载目录下一级文件信息 if (!Array.isArray(e.node.children) || e.node.children.length === 0) { readDir(e.node.key).then(fileStateList => { - if (Array.isArray(fileStateList[0].childList) && fileStateList[0].childList.length > 0) { + if (Array.isArray(fileStateList[0].children) && fileStateList[0].children.length > 0) { dispatch(nextDirAdd({selectDirKey: e.node.key, fileStateList})) // 添加下级节点 addChildNode(defaultValueState, flushTree(fileStateList)) @@ -259,7 +289,7 @@ const ItemTree = (prop) => { , dirFlag && - setState("")}/> + itemTreeAddFile(dirMessage)} closeMenu={() => setState("")}/> , !dirFlag && @@ -272,9 +302,11 @@ const ItemTree = (prop) => { {setState("")}}>关闭菜单 ] return ( - - {menuItem} - +
+ + {menuItem} + +
) } @@ -294,7 +326,7 @@ const ItemTree = (prop) => { // 是否自动展开父节点 autoExpandParent={autoExpandParent} showIcon={true} - // defaultSelectedKeys={[useSelector(state => state.tableBarItem.activeKey)]} + selectedKeys={[useSelector(state => state.tableBarItem.activeKey)]} defaultExpandedKeys={useSelector(state => state.tableBarItem.expandedKeyList)} // treeNodes 数据,如果设置则不需要手动构造 TreeNode 节点(key 在整个树范围内唯一) treeData={defaultValueState} diff --git a/src/pages/Note/Hlexical/index.jsx b/src/pages/Note/Hlexical/index.jsx index 9b6e6f9..707fb0c 100644 --- a/src/pages/Note/Hlexical/index.jsx +++ b/src/pages/Note/Hlexical/index.jsx @@ -68,7 +68,10 @@ function ImportFilePlugin(props) { useEffect(() => { if (props.filePath){ importFile(props.filePath).then(value => { - + console.log("value",value,isEmpty(value)) + if (isEmpty(value)){ + return + } if (props.filePath.endsWith(".md")){ const root = $getRoot(); const firstChild = root.getFirstChild(); @@ -148,7 +151,7 @@ export default function Hlexical(props) { if ((lastId === "" || lastId !== store.getState().pushHotkeys.id) && store.getState().pushHotkeys.data === SAVE) { setLastId(store.getState().pushHotkeys.id); importFile(filePath).then(value => { - let save = md5(resultSave) !== md5(JSON.stringify(JSON.parse(value.toString()))); + let save = (isEmpty(value))||md5(resultSave) !== md5(JSON.stringify(JSON.parse(value.toString()))); if (save) { console.log("保存重写") overWriteFile(filePath, resultSave) diff --git a/src/redux/dirMessage_reducer.js b/src/redux/dirMessage_reducer.js index f6280ee..7775a31 100644 --- a/src/redux/dirMessage_reducer.js +++ b/src/redux/dirMessage_reducer.js @@ -1,10 +1,16 @@ import {createSlice} from '@reduxjs/toolkit' import {isEmpty} from "../utils/ObjectUtils"; +import {fullFileNameFormat, getFileFullNameByPath} from "../utils/PathOperate"; /* + fileTitle:文件名 + fileName:文件名.文件扩展名 + fileDir:文件路径 + filePath:文件路径+fileName + "fileName": filePath, "filePath": filePath, "dirFlag": true, - "childList": fileChildList + "children": fileChildList */ export const dirMessageSlice = createSlice({ name: 'dirMessage', @@ -53,8 +59,8 @@ export const dirMessageSlice = createSlice({ state.data = state.data.filter(file=>{ if (file.filePath === selectDirKey && file.dirFlag) { return false; - } else if (file.childList.length > 0 && selectDirKey.startsWith(file.filePath)) { - file.childList = filterChild(file.childList, selectDirKey) + } else if (file.children.length > 0 && selectDirKey.startsWith(file.filePath)) { + file.children = filterChild(file.children, selectDirKey) return true; }else { return true; @@ -68,10 +74,10 @@ export const dirMessageSlice = createSlice({ // 遍历文件树,找到对应的key并加入其中, // 如果包含下级目录则不更新,在刷新中更新。 state.data.forEach(file => { - if (file.filePath === selectDirKey && file.dirFlag && file.childList.length === 0) { - file.childList.push(action.payload.fileStateList[0].childList) - } else if (file.childList.length > 0) { - findChild(file.childList, action, selectDirKey) + if (file.filePath === selectDirKey && file.dirFlag && file.children.length === 0) { + file.children.push(action.payload.fileStateList[0].children) + } else if (file.children.length > 0) { + findChild(file.children, action, selectDirKey) } }) }, @@ -82,9 +88,9 @@ export const dirMessageSlice = createSlice({ // 遍历文件树,找到对应的key并加入其中, state.data.forEach(file => { if (file.filePath === selectDirKey && file.dirFlag) { - file.childList=action.payload.fileStateList[0].childList - } else if (file.childList.length > 0) { - refreshChild(file.childList, action, selectDirKey) + file.children=action.payload.fileStateList[0].children + } else if (file.children.length > 0) { + refreshChild(file.children, action, selectDirKey) } }) }, @@ -96,9 +102,9 @@ export const dirMessageSlice = createSlice({ state.data.forEach(file => { if (file.filePath === oldFilePath) { file.filePath = newFilePath - file.fileName = newFilePath.substring(newFilePath.lastIndexOf("/")+1) - } else if (file.childList.length > 0 && oldFilePath.startsWith(file.filePath)) { - updateFileNameChild(file.childList, oldFilePath, newFilePath) + file.fileName = getFileFullNameByPath(newFilePath) + } else if (file.children.length > 0 && oldFilePath.startsWith(file.filePath)) { + updateFileNameChild(file.children, oldFilePath, newFilePath) } }) }, @@ -107,10 +113,10 @@ export const dirMessageSlice = createSlice({ let filePath = action.payload.filePath let fileName = action.payload.fileName let fileMessage = { - "fileName": fileName.replace(filePath+"/",""), + "fileName": getFileFullNameByPath(fileName), "filePath": fileName, "dirFlag": false, - "childList": [] + "children": [] } // 查找旧文件并且修改文件信息 state.data.forEach(file => { @@ -120,8 +126,8 @@ export const dirMessageSlice = createSlice({ }else { file.children=[fileMessage] } - } else if (file.childList.length > 0 && file.filePath.startsWith(filePath)) { - dirFileAddChild(file.childList, filePath, fileMessage) + } else if (file.children.length > 0 && file.filePath.startsWith(filePath)) { + dirFileAddChild(file.children, filePath, fileMessage) } }) }, @@ -130,8 +136,8 @@ export const dirMessageSlice = createSlice({ state.data = state.data.filter(file=>{ if (file.filePath === filePath && !file.dirFlag) { return false; - } else if (file.childList.length > 0 && filePath.startsWith(file.filePath)) { - file.childList = dirFileRemoveChild(file.childList, filePath) + } else if (file.children.length > 0 && filePath.startsWith(file.filePath)) { + file.children = dirFileRemoveChild(file.children, filePath) return true; }else { return true; @@ -145,8 +151,8 @@ function dirFileRemoveChild(fileList, selectDirKey) { return fileList.filter(file => { if (file.filePath === selectDirKey && !file.dirFlag) { return false - }else if (file.dirFlag && selectDirKey.startsWith(file.filePath) && Array.isArray(file.childList) && file.childList.length > 0) { - dirFileRemoveChild(file.childList, selectDirKey) + }else if (file.dirFlag && selectDirKey.startsWith(file.filePath) && Array.isArray(file.children) && file.children.length > 0) { + dirFileRemoveChild(file.children, selectDirKey) return true }else { return true @@ -162,8 +168,8 @@ function dirFileAddChild(fileList, filePath, fileMessage){ }else { file.children=[fileMessage] } - } else if (file.childList.length > 0 && file.filePath.startsWith(filePath)) { - dirFileAddChild(file.childList, filePath, fileMessage) + } else if (file.children.length > 0 && file.filePath.startsWith(filePath)) { + dirFileAddChild(file.children, filePath, fileMessage) } }) } @@ -171,8 +177,8 @@ function filterChild(fileList, selectDirKey) { return fileList.filter(file => { if (file.filePath === selectDirKey && file.dirFlag) { return false - }else if (file.dirFlag && selectDirKey.startsWith(file.filePath) && Array.isArray(file.childList) && file.childList.length > 0) { - filterChild(file.childList, selectDirKey) + }else if (file.dirFlag && selectDirKey.startsWith(file.filePath) && Array.isArray(file.children) && file.children.length > 0) { + filterChild(file.children, selectDirKey) return true }else { return true @@ -183,11 +189,11 @@ function filterChild(fileList, selectDirKey) { function refreshChild(fileList, action, selectDirKey) { fileList.forEach(file => { if (file.filePath === selectDirKey && file.dirFlag) { - file.childList = action.payload.fileStateList[0].childList + file.children = action.payload.fileStateList[0].children return } - if (file.dirFlag && Array.isArray(file.childList) && file.childList.length > 0) { - refreshChild(file.childList, action, selectDirKey) + if (file.dirFlag && Array.isArray(file.children) && file.children.length > 0) { + refreshChild(file.children, action, selectDirKey) } }) } @@ -195,12 +201,12 @@ function refreshChild(fileList, action, selectDirKey) { function findChild(fileList, action, selectDirKey) { fileList.forEach(file => { if (file.filePath === selectDirKey && file.dirFlag && - (isEmpty(file.childList) || (Array.isArray(file.childList) && file.childList.length === 0))) { - file.childList = action.payload.fileStateList[0].childList + (isEmpty(file.children) || (Array.isArray(file.children) && file.children.length === 0))) { + file.children = action.payload.fileStateList[0].children return } - if (file.dirFlag && Array.isArray(file.childList) && file.childList.length > 0) { - findChild(file.childList, action, selectDirKey) + if (file.dirFlag && Array.isArray(file.children) && file.children.length > 0) { + findChild(file.children, action, selectDirKey) } }) } @@ -209,10 +215,10 @@ function updateFileNameChild(fileList, oldFilePath, newFilePath) { fileList.forEach(file => { if (file.filePath === oldFilePath) { file.filePath = newFilePath - file.fileName = newFilePath.substring(newFilePath.lastIndexOf("/")+1) + file.fileName = getFileFullNameByPath(newFilePath) return - }else if (Array.isArray(file.childList) && file.childList.length > 0 && oldFilePath.startsWith(file.filePath)) { - updateFileNameChild(file.childList, oldFilePath, newFilePath) + }else if (Array.isArray(file.children) && file.children.length > 0 && oldFilePath.startsWith(file.filePath)) { + updateFileNameChild(file.children, oldFilePath, newFilePath) } }) } diff --git a/src/redux/tableBarItem_reducer.js b/src/redux/tableBarItem_reducer.js index 5504c6b..bf01ea6 100644 --- a/src/redux/tableBarItem_reducer.js +++ b/src/redux/tableBarItem_reducer.js @@ -1,5 +1,6 @@ import { createSlice } from '@reduxjs/toolkit' import {isEmpty} from "../utils/ObjectUtils"; +import {getFileFullNameByPath} from "../utils/PathOperate"; /** * { @@ -49,7 +50,7 @@ export const tableBarItemSlice = createSlice({ if (file.key === oldFilePath) { file.key = newFilePath file.children= newFilePath - file.label = newFilePath.substring(newFilePath.lastIndexOf("/")+1) + file.label = getFileFullNameByPath(newFilePath) } }) if (state.activeKey===oldFilePath){ @@ -66,9 +67,7 @@ export const tableBarItemSlice = createSlice({ if (file.key===state.activeKey){ file.children=action.payload.filePath; file.key = action.payload.filePath; - let split = action.payload.filePath.split("/"); - console.log("action.payload.filePath.split()",split) - file.label =split[split.length-1] + file.label = getFileFullNameByPath(action.payload.filePath) } }) state.activeKey = action.payload.filePath diff --git a/src/utils/File/index.jsx b/src/utils/File/index.jsx index e4593da..0303a38 100644 --- a/src/utils/File/index.jsx +++ b/src/utils/File/index.jsx @@ -1,6 +1,6 @@ const fs = window.require("fs").promises const {ipcRenderer} = window.require('electron') - +const pathOp = window.require("path") export async function readDir(filePath){ const files = await fs.readdir(filePath); const fileStateList = [] @@ -9,19 +9,19 @@ export async function readDir(filePath){ "fileName": filePath, "filePath": filePath, "dirFlag": true, - "childList": fileChildList + "children": fileChildList }) for (let i = 0; i < files.length; i++) { - const state = await fs.stat(filePath + '/' + files[i]); + const state = await fs.stat(filePath + pathOp.sep + files[i]); if (state.isDirectory() || files[i].endsWith(".md") || files[i].endsWith(".html") || files[i].endsWith(".lexical")) { fileChildList.push({ 'fileName': files[i], - "filePath": filePath + '/' + files[i], + "filePath": filePath + pathOp.sep + files[i], 'dirFlag': state.isDirectory(), - "childList":[] + "children":[] }) } } @@ -49,14 +49,4 @@ export async function updateFileName(oldFileName,newFileName){ export async function saveFileWithName(){ return ipcRenderer.invoke("saveFileWithName" ) -} - -export function getFileNameByPath(fileName){ - // 获取文件名 - let fileFullName = fileName.substring(fileName.lastIndexOf("/")+1); - let number = fileFullName.lastIndexOf("."); - if (number>0){ - return fileFullName.substring(0,number); - } - return fileFullName } \ No newline at end of file diff --git a/src/utils/PathOperate/index.jsx b/src/utils/PathOperate/index.jsx new file mode 100644 index 0000000..c4e7a57 --- /dev/null +++ b/src/utils/PathOperate/index.jsx @@ -0,0 +1,23 @@ +const pathOperate = window.require("path") + +export function getFileNameByPath(fileName){ + return pathOperate.parse(fileName).name +} +export function getFileFullNameByPath(fileName){ + return pathOperate.parse(fileName).base +} + +export function replaceFileNameByFilePath(filePath,fileName){ + let parsedPath = pathOperate.parse(fileName); + return pathOperate.format({"dir":parsedPath.dir,"base":fileName+parsedPath.ext}) +} +export function getFileDirByPath(fileName){ + return pathOperate.parse(fileName).dir +} +export function fileNameFormat(dir,fileName,ext){ + return pathOperate.format({"dir":dir,"base":fileName+ext}) +} + +export function fullFileNameFormat(dir,fileName){ + return pathOperate.format({"dir":dir,"base":fileName}) +} \ No newline at end of file