From 8c6991afb3c2a607b89bca5420a3b609f2b61655 Mon Sep 17 00:00:00 2001 From: duanhongbo <6860300@qq.com> Date: Fri, 27 Nov 2020 18:04:13 +0800 Subject: [PATCH] refactor: use shineout tree replace antd tree --- package-lock.json | 224 ++++++++++++- package.json | 3 + .../{Properties.tsx => Explorer.tsx} | 311 ++++++++++-------- render-process/index.css | 24 +- render-process/index.tsx | 4 +- webpack.config.js | 7 +- 6 files changed, 420 insertions(+), 153 deletions(-) rename render-process/{Properties.tsx => Explorer.tsx} (54%) diff --git a/package-lock.json b/package-lock.json index 76c92b2..03938f4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2451,6 +2451,15 @@ "sha.js": "^2.4.8" } }, + "create-react-context": { + "version": "0.2.3", + "resolved": "https://registry.npm.taobao.org/create-react-context/download/create-react-context-0.2.3.tgz", + "integrity": "sha1-nsFAppFKIu8EuLCbd3HeiVZ8tvM=", + "requires": { + "fbjs": "^0.8.0", + "gud": "^1.0.0" + } + }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npm.taobao.org/cross-spawn/download/cross-spawn-6.0.5.tgz", @@ -2663,6 +2672,14 @@ "mimic-response": "^1.0.0" } }, + "deep-eql": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/deep-eql/download/deep-eql-4.0.0.tgz", + "integrity": "sha1-xwrycTpOGNnCwSA/+dEau9Ucj70=", + "requires": { + "type-detect": "^4.0.0" + } + }, "deep-extend": { "version": "0.6.0", "resolved": "https://registry.npm.taobao.org/deep-extend/download/deep-extend-0.6.0.tgz", @@ -3506,6 +3523,14 @@ "dev": true, "optional": true }, + "encoding": { + "version": "0.1.13", + "resolved": "https://registry.npm.taobao.org/encoding/download/encoding-0.1.13.tgz", + "integrity": "sha1-VldK/deR9UqOmyeFwFgqLSYhD6k=", + "requires": { + "iconv-lite": "^0.6.2" + } + }, "end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npm.taobao.org/end-of-stream/download/end-of-stream-1.4.4.tgz", @@ -3874,6 +3899,35 @@ "reusify": "^1.0.4" } }, + "fbjs": { + "version": "0.8.17", + "resolved": "https://registry.npm.taobao.org/fbjs/download/fbjs-0.8.17.tgz?cache=0&sync_timestamp=1602048886093&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffbjs%2Fdownload%2Ffbjs-0.8.17.tgz", + "integrity": "sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=", + "requires": { + "core-js": "^1.0.0", + "isomorphic-fetch": "^2.1.1", + "loose-envify": "^1.0.0", + "object-assign": "^4.1.0", + "promise": "^7.1.1", + "setimmediate": "^1.0.5", + "ua-parser-js": "^0.7.18" + }, + "dependencies": { + "core-js": { + "version": "1.2.7", + "resolved": "https://registry.npm.taobao.org/core-js/download/core-js-1.2.7.tgz?cache=0&sync_timestamp=1606329319777&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcore-js%2Fdownload%2Fcore-js-1.2.7.tgz", + "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=" + }, + "promise": { + "version": "7.3.1", + "resolved": "https://registry.npm.taobao.org/promise/download/promise-7.3.1.tgz", + "integrity": "sha1-BktyYCsY+Q8pGSuLG8QY/9Hr078=", + "requires": { + "asap": "~2.0.3" + } + } + } + }, "fd-slicer": { "version": "1.1.0", "resolved": "http://registry.npm.taobao.org/fd-slicer/download/fd-slicer-1.1.0.tgz", @@ -4384,6 +4438,11 @@ "lodash": "^4.17.15" } }, + "gud": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/gud/download/gud-1.0.0.tgz", + "integrity": "sha1-pIlYGxfmpwvsqavjrlfeekmYUsA=" + }, "has-flag": { "version": "3.0.0", "resolved": "http://registry.npm.taobao.org/has-flag/download/has-flag-3.0.0.tgz", @@ -4566,7 +4625,6 @@ "version": "0.6.2", "resolved": "https://registry.npm.taobao.org/iconv-lite/download/iconv-lite-0.6.2.tgz", "integrity": "sha1-zhPRh1sMOmdL1qBLf3awGxtt7QE=", - "dev": true, "requires": { "safer-buffer": ">= 2.1.2 < 3.0.0" } @@ -4598,6 +4656,18 @@ "integrity": "sha1-8VCotQo0KJsz4i9YiavU2AFvDlc=", "dev": true }, + "image-size": { + "version": "0.5.5", + "resolved": "https://registry.npm.taobao.org/image-size/download/image-size-0.5.5.tgz?cache=0&sync_timestamp=1603731285656&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fimage-size%2Fdownload%2Fimage-size-0.5.5.tgz", + "integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=", + "dev": true, + "optional": true + }, + "immer": { + "version": "4.0.2", + "resolved": "https://registry.npm.taobao.org/immer/download/immer-4.0.2.tgz", + "integrity": "sha1-n/D834jgb5Jhill4zuy1iE5jNVk=" + }, "import-lazy": { "version": "2.1.0", "resolved": "https://registry.npm.taobao.org/import-lazy/download/import-lazy-2.1.0.tgz", @@ -4880,6 +4950,11 @@ "isobject": "^3.0.1" } }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/is-stream/download/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npm.taobao.org/is-typedarray/download/is-typedarray-1.0.0.tgz", @@ -4930,6 +5005,15 @@ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true }, + "isomorphic-fetch": { + "version": "2.2.1", + "resolved": "https://registry.npm.taobao.org/isomorphic-fetch/download/isomorphic-fetch-2.2.1.tgz?cache=0&sync_timestamp=1600844260369&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fisomorphic-fetch%2Fdownload%2Fisomorphic-fetch-2.2.1.tgz", + "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", + "requires": { + "node-fetch": "^1.0.1", + "whatwg-fetch": ">=0.10.0" + } + }, "jake": { "version": "10.8.2", "resolved": "https://registry.npm.taobao.org/jake/download/jake-10.8.2.tgz", @@ -5041,6 +5125,12 @@ "integrity": "sha1-B8BQNKbDSfoG4k+jWqdttFgM5N0=", "dev": true }, + "klona": { + "version": "2.0.4", + "resolved": "https://registry.npm.taobao.org/klona/download/klona-2.0.4.tgz", + "integrity": "sha1-e7Hjr/sMuGJFR+9+j2cI6i4538A=", + "dev": true + }, "latest-version": { "version": "5.1.0", "resolved": "https://registry.npm.taobao.org/latest-version/download/latest-version-5.1.0.tgz", @@ -5056,6 +5146,82 @@ "integrity": "sha1-iCY2pyRcLP5uCk47psXWihN+XGU=", "dev": true }, + "less": { + "version": "3.12.2", + "resolved": "https://registry.npm.taobao.org/less/download/less-3.12.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fless%2Fdownload%2Fless-3.12.2.tgz", + "integrity": "sha1-FX5t0ypohp34hZMUrTjnAhGvOrQ=", + "dev": true, + "requires": { + "errno": "^0.1.1", + "graceful-fs": "^4.1.2", + "image-size": "~0.5.0", + "make-dir": "^2.1.0", + "mime": "^1.4.1", + "native-request": "^1.0.5", + "source-map": "~0.6.0", + "tslib": "^1.10.0" + }, + "dependencies": { + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npm.taobao.org/mime/download/mime-1.6.0.tgz", + "integrity": "sha1-Ms2eXGRVO9WNGaVor0Uqz/BJgbE=", + "dev": true, + "optional": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "dev": true, + "optional": true + } + } + }, + "less-loader": { + "version": "7.1.0", + "resolved": "https://registry.npm.taobao.org/less-loader/download/less-loader-7.1.0.tgz?cache=0&sync_timestamp=1605095927771&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fless-loader%2Fdownload%2Fless-loader-7.1.0.tgz", + "integrity": "sha1-lY1B6G194Ly0kHEe4PI1qp3Flqo=", + "dev": true, + "requires": { + "klona": "^2.0.4", + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "dependencies": { + "json5": { + "version": "2.1.3", + "resolved": "https://registry.npm.taobao.org/json5/download/json5-2.1.3.tgz", + "integrity": "sha1-ybD3+pIzv+WAf+ZvzzpWF+1ZfUM=", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/loader-utils/download/loader-utils-2.0.0.tgz", + "integrity": "sha1-5MrOW4FtQloWa18JfhDNErNgZLA=", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/schema-utils/download/schema-utils-3.0.0.tgz", + "integrity": "sha1-Z1AvaqK2ai1AMrQnmilEl4oJE+8=", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + } + } + }, "load-json-file": { "version": "2.0.0", "resolved": "https://registry.npm.taobao.org/load-json-file/download/load-json-file-2.0.0.tgz", @@ -5566,6 +5732,13 @@ "to-regex": "^3.0.1" } }, + "native-request": { + "version": "1.0.8", + "resolved": "https://registry.npm.taobao.org/native-request/download/native-request-1.0.8.tgz?cache=0&sync_timestamp=1603412804149&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnative-request%2Fdownload%2Fnative-request-1.0.8.tgz", + "integrity": "sha1-j2a/YG4PfqJ8DlmV6y9dA+M65vs=", + "dev": true, + "optional": true + }, "neo-async": { "version": "2.6.2", "resolved": "https://registry.npm.taobao.org/neo-async/download/neo-async-2.6.2.tgz", @@ -5578,6 +5751,15 @@ "integrity": "sha1-ozeKdpbOfSI+iPybdkvX7xCJ42Y=", "dev": true }, + "node-fetch": { + "version": "1.7.3", + "resolved": "https://registry.npm.taobao.org/node-fetch/download/node-fetch-1.7.3.tgz?cache=0&sync_timestamp=1599309206591&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnode-fetch%2Fdownload%2Fnode-fetch-1.7.3.tgz", + "integrity": "sha1-mA9vcthSEaU0fGsrwYxbhMPrR+8=", + "requires": { + "encoding": "^0.1.11", + "is-stream": "^1.0.1" + } + }, "node-libs-browser": { "version": "2.2.1", "resolved": "https://registry.npm.taobao.org/node-libs-browser/download/node-libs-browser-2.2.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnode-libs-browser%2Fdownload%2Fnode-libs-browser-2.2.1.tgz", @@ -7075,8 +7257,7 @@ "safer-buffer": { "version": "2.1.2", "resolved": "http://registry.npm.taobao.org/safer-buffer/download/safer-buffer-2.1.2.tgz", - "integrity": "sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo=", - "dev": true + "integrity": "sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo=" }, "sanitize-filename": { "version": "1.6.3", @@ -7201,8 +7382,7 @@ "setimmediate": { "version": "1.0.5", "resolved": "http://registry.npm.taobao.org/setimmediate/download/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" }, "sha.js": { "version": "2.4.11", @@ -7234,6 +7414,25 @@ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "dev": true }, + "shineout": { + "version": "1.6.1", + "resolved": "https://registry.npm.taobao.org/shineout/download/shineout-1.6.1.tgz", + "integrity": "sha1-cGf1X6MG4CHHZ5MComI2t+xOfgo=", + "requires": { + "classnames": "^2.2.5", + "create-react-context": "^0.2.3", + "date-fns": "2.0.0-alpha.10", + "deep-eql": "^4.0.0", + "immer": "^4.0.0" + }, + "dependencies": { + "date-fns": { + "version": "2.0.0-alpha.10", + "resolved": "https://registry.npm.taobao.org/date-fns/download/date-fns-2.0.0-alpha.10.tgz?cache=0&sync_timestamp=1598884225872&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdate-fns%2Fdownload%2Fdate-fns-2.0.0-alpha.10.tgz", + "integrity": "sha1-0zRFOk2OBkPb7i1wQ2/JJiwV2oA=" + } + } + }, "signal-exit": { "version": "3.0.3", "resolved": "https://registry.npm.taobao.org/signal-exit/download/signal-exit-3.0.3.tgz?cache=0&sync_timestamp=1600349108829&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsignal-exit%2Fdownload%2Fsignal-exit-3.0.3.tgz", @@ -8053,6 +8252,11 @@ "dev": true, "optional": true }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npm.taobao.org/type-detect/download/type-detect-4.0.8.tgz", + "integrity": "sha1-dkb7XxiHHPu3dJ5pvTmmOI63RQw=" + }, "type-fest": { "version": "0.13.1", "resolved": "https://registry.npm.taobao.org/type-fest/download/type-fest-0.13.1.tgz?cache=0&sync_timestamp=1601425309553&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftype-fest%2Fdownload%2Ftype-fest-0.13.1.tgz", @@ -8080,6 +8284,11 @@ "integrity": "sha1-FTu9Ro7wdyXB35x36LRT+NNqu6U=", "dev": true }, + "ua-parser-js": { + "version": "0.7.22", + "resolved": "https://registry.npm.taobao.org/ua-parser-js/download/ua-parser-js-0.7.22.tgz?cache=0&sync_timestamp=1599900430227&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fua-parser-js%2Fdownload%2Fua-parser-js-0.7.22.tgz", + "integrity": "sha1-lg32Cl+RHqjxyBjzdHuZxuF36uM=" + }, "unified": { "version": "9.2.0", "resolved": "https://registry.npm.taobao.org/unified/download/unified-9.2.0.tgz?cache=0&sync_timestamp=1598034253769&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Funified%2Fdownload%2Funified-9.2.0.tgz", @@ -8652,6 +8861,11 @@ } } }, + "whatwg-fetch": { + "version": "3.5.0", + "resolved": "https://registry.npm.taobao.org/whatwg-fetch/download/whatwg-fetch-3.5.0.tgz", + "integrity": "sha1-YFos0KcUbl2xQeKdHGKrhMDEyGg=" + }, "whatwg-mimetype": { "version": "2.3.0", "resolved": "http://registry.npm.taobao.org/whatwg-mimetype/download/whatwg-mimetype-2.3.0.tgz", diff --git a/package.json b/package.json index 2164a32..3be0a79 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,8 @@ "electron-localshortcut": "^3.2.1", "electron-packager": "^15.1.0", "file-loader": "^6.1.1", + "less": "^3.12.2", + "less-loader": "^7.1.0", "source-map-loader": "^1.1.0", "style-loader": "^2.0.0", "ts-loader": "^8.0.4", @@ -56,6 +58,7 @@ "react-markdown": "^5.0.2", "rimraf": "^3.0.2", "sanitize-filename": "^1.6.3", + "shineout": "^1.6.1", "sync-request": "^6.1.0" } } diff --git a/render-process/Properties.tsx b/render-process/Explorer.tsx similarity index 54% rename from render-process/Properties.tsx rename to render-process/Explorer.tsx index b1a65ea..0e04e2c 100644 --- a/render-process/Properties.tsx +++ b/render-process/Explorer.tsx @@ -1,68 +1,55 @@ import React, { ChangeEvent, Component } from "react"; -import { Input, Tree, Dropdown } from "antd"; +import { Input } from "antd"; +import { Tree } from "shineout"; +import {FolderOutlined ,FileOutlined,FolderOpenOutlined} from "@ant-design/icons"; import * as fs from "fs"; import * as path from "path"; import { ipcRenderer } from "electron"; import MainEventType from "../common/MainEventType"; -import { DataNode } from "antd/lib/tree"; -import { EventDataNode, IconType } from "rc-tree/lib/interface"; -const { Search } = Input; -const { DirectoryTree, TreeNode } = Tree; +const {Search} = Input; +const DirectoryTree = Tree; -export interface PropertiesProps { - workdir: string; - onOpenTree: (path: string) => void; - onDeleteTree: (path: string) => void; -} -class FileDataNode implements DataNode { - checkable?: boolean; - children?: FileDataNode[]; - disabled?: boolean; - disableCheckbox?: boolean; - icon?: IconType; - isLeaf?: boolean; - key: React.ReactText; - title?: React.ReactNode; - selectable?: boolean; - switcherIcon?: IconType; - className?: string; - style?: React.CSSProperties; +class FileDataNode { + name: string; //display name + filepath: string; //file full path + isFolder: boolean; parent: FileDataNode; visible: boolean = true; + children: FileDataNode[]; public constructor(init?: Partial) { Object.assign(this, init); } - get isFolder() { - return this.isLeaf !== void 0 && !this.isLeaf; + get id() { + return this.filepath; } - get name() { - return this.title as string; + get text() { + return this.name; } get path() { - return this.key as string; + return this.filepath; } public getRenderData() { - if(!this.visible){ + if (!this.visible) { return null; } - let ret = { - title: this.title, - key: this.key, - isLeaf: this.isLeaf, - children: new Array() - }; + let ret = new FileDataNode({ + name: this.name, + filepath: this.filepath, + isFolder: this.isFolder, + children: new Array(), + }); for (const child of this.children) { const data = child.getRenderData(); - if(data){ + if (data) { ret.children.push(data); } } @@ -70,7 +57,7 @@ class FileDataNode implements DataNode { } loadChilds(recursive?: boolean) { - const folder = this.key as string; + const folder = this.path; if (folder == "" || !fs.existsSync(folder)) { return []; } @@ -82,9 +69,9 @@ class FileDataNode implements DataNode { const isFolder = stat.isDirectory(); const name = isFolder ? filename : filename.slice(0, -5); const node = new FileDataNode({ - title: name, - key: fullPath, - isLeaf: !isFolder, + name: name, + filepath: fullPath, + isFolder: isFolder, parent: this, }); @@ -92,15 +79,60 @@ class FileDataNode implements DataNode { isFolder && recursive ? (node.loadChilds(recursive) as FileDataNode[]) : []), list.push(node); }); + list.sort((a, b) => { + const av = a.isFolder ? 100 : 0; + const bv = b.isFolder ? 100 : 0; + return bv - av; + }); return list; } + + // async updateChilds(recursive?: boolean): Promise { + // const folder = this.path; + // if (folder == "" || !fs.existsSync(folder)) { + // return []; + // } + // this.loading = true; + // await fs.promises.readdir(folder).then((files) => { + // this.loading = false; + // let list = new Array(); + // files.forEach((filename) => { + // const fullPath = path.join(folder, filename); + // const stat = fs.statSync(fullPath); + // const isFolder = stat.isDirectory(); + // const name = isFolder ? filename : filename.slice(0, -5); + // const node = new FileDataNode({ + // name: name, + // filepath: fullPath, + // isFolder: isFolder, + // parent: this, + // children: [], + // }); + + // if (isFolder && recursive) { + // node.updateChilds(recursive).then((children)=>{ + // node.children = children; + // }); + // } + // list.push(node); + // }); + // list.sort((a, b) => { + // const av = a.isFolder ? 100 : 0; + // const bv = b.isFolder ? 100 : 0; + // return bv - av; + // }); + // this.children = list; + // }); + // return this.children; + // } + addChild(filePath: string) { const isDir = fs.statSync(filePath).isDirectory(); const newNode = new FileDataNode({ - title: path.basename(filePath), - key: filePath, - isLeaf: !isDir, + name: path.basename(filePath), + filepath: filePath, + isFolder: isDir, parent: this, children: [], }); @@ -116,15 +148,17 @@ class FileDataNode implements DataNode { } expandSelf(recursive: boolean = true) { - if (this.isFolder) this.children = this.loadChilds(recursive); + if (this.isFolder) { + this.children = this.loadChilds(recursive); + } } - findChild(key: string): FileDataNode { + findChild(id: string): FileDataNode { for (const child of this.children) { - if (child.key == key) { + if (child.id == id) { return child; } else { - const ret = child.findChild(key); + const ret = child.findChild(id); if (ret) { return ret; } @@ -142,12 +176,12 @@ class FileDataNode implements DataNode { return ret; } - setVisible(keyWord:string){ + setVisible(keyWord: string) { let ret = false; - for (let i = this.children.length-1;i >= 0;i--) { + for (let i = this.children.length - 1; i >= 0; i--) { const child = this.children[i]; - if (child.isLeaf) { - const keyStr = child.title as string; + if (!child.isFolder) { + const keyStr = child.id; child.visible = keyStr.includes(keyWord); } else { child.visible = child.setVisible(keyWord); @@ -164,9 +198,17 @@ class FileDataNode implements DataNode { // children?: NodeData[]; } -interface PropertiesState { +export interface ExplorerProps { + workdir: string; + onOpenTree: (path: string) => void; + onDeleteTree: (path: string) => void; +} + + +interface ExplorerState { root: FileDataNode; searchKey: string; + selectedKey: string; defaultExpandedKeys: string[]; expandedKeys: string[]; autoExpandParent: boolean; @@ -185,10 +227,11 @@ const NodeActions: { [x: string]: string } = { ["reveal_in_explorer"]: "Reveal In File Explorer", }; -export default class Properties extends Component { - state: PropertiesState = { - root: null, +export default class Explorer extends Component { + state: ExplorerState = { + root: this.getRootNode(this.props.workdir), searchKey: "", + selectedKey: "", rightClickNode: null, expandedKeys: [], defaultExpandedKeys: [], @@ -197,7 +240,7 @@ export default class Properties extends Component { curWorkdir: string = ""; - shouldComponentUpdate(nextProps: PropertiesProps) { + shouldComponentUpdate(nextProps: ExplorerProps) { const shouldUpdate = this.curWorkdir != nextProps.workdir; this.curWorkdir = nextProps.workdir; return shouldUpdate; @@ -226,21 +269,23 @@ export default class Properties extends Component { return; } const root = this.getRootNode(workdir); - root.expandSelf(); + root.expandSelf() this.setState({ root: root, - expandedKeys: [root.key], - defaultExpandedKeys: [root.key] + expandedKeys: [root.id], + defaultExpandedKeys: [root.id], }); + + this.forceUpdate(); } getRootNode(workdir: string) { return new FileDataNode({ - title: path.basename(workdir), - key: workdir, - isLeaf: false, + name: path.basename(workdir), + filepath: workdir, + isFolder: true, parent: null, - children: [], + children: [] }); } @@ -268,28 +313,27 @@ export default class Properties extends Component { const expandedKeys = this.state.root .getList() .map((item) => { - if (!item.isLeaf) - return null; - const title = item.title as string; + if (item.isFolder) return null; + const title = item.text; if (title.includes(value) && item.parent) { - return item.parent.key; + return item.parent.id; } return null; }) .filter((item, i, self) => item && self.indexOf(item) === i); const root = this.state.root; - root.setVisible(value||""); + root.setVisible(value || ""); if (value && value.length > 0) { this.setState({ - root:root, + root: root, searchKey: value, expandedKeys: expandedKeys, autoExpandParent: true, }); } else { this.setState({ - root:root, + root: root, searchKey: "", expandedKeys: this.state.defaultExpandedKeys, autoExpandParent: false, @@ -299,97 +343,86 @@ export default class Properties extends Component { this.forceUpdate(); } - titleRender(node: DataNode): React.ReactNode { - const titleStr = node.title as string; + renderItem(node: FileDataNode) { + if(!node.visible){ + return null; + } + const titleStr = node.text; const searchKey = this.state.searchKey; const index = titleStr.indexOf(searchKey); const beforeStr = titleStr.substr(0, index); const afterStr = titleStr.substr(index + searchKey.length); + const expended = this.state.expandedKeys.includes(node.id ); - //return ({titleStr}) - return node.isLeaf && index > -1 ? ( - - {beforeStr} - {searchKey} - {afterStr} - - ) : ( - {titleStr} - ); - } - - handleOnLoadData(loadNode: EventDataNode) { - return new Promise((resolve) => { - const root = this.state.root; - - const node = root.findChild(loadNode.key as string); - if (node) { - node.expandSelf(); - this.setState({ root: root }); - this.forceUpdate(); - } - - resolve(); - return; - }); + return ( +
{}} + > + {node.isFolder?(expended?:):} + {!node.isFolder && index > -1 ? ( + + {beforeStr} + {searchKey} + {afterStr} + + ) : ( + {titleStr} + )} +
+ ); } render() { - console.log("render Properties"); + console.log("render Explorer"); const { onOpenTree, onDeleteTree, workdir } = this.props; + const root = this.state.root; + if (!workdir || workdir === "") { + return `请打开workspace.json文件`; + } + const nodes = root ? [root.getRenderData()] : []; - return nodes.length ? ( + + return (
{ + // onChange={(e) => { // const value = e.target.value?.toLowerCase(); // this.handleOnSearch(value); // }} - onSearch={ - (value,event)=>{ - this.handleOnSearch(value?.toLowerCase()); - } - } - /> + onSearch={(value, event) => { + this.handleOnSearch(value?.toLowerCase()); + }} + /> + { - //console.log("onSelect", keys, info); - if (info.node.isLeaf) { - onOpenTree(keys[0] as string); + keygen="id" + data={nodes} + line={true} + doubleClickExpand + // expandIcons={[, ]} + //defaultValue={[root.id]} + defaultExpanded={[root.id]} + expanded={this.state.expandedKeys} + value={[this.state.selectedKey]} + onExpand={(expanded)=>{ + this.setState({ expandedKeys: expanded }) + }} + renderItem={this.renderItem.bind(this)} + onClick={(node: FileDataNode) => { + if (!node.isFolder) { + onOpenTree(node.path); + this.setState({ + selectedKey:node.id + }) } }} - onExpand={(keys, info) => { - this.setState({ - expandedKeys: keys, - autoExpandParent: false - }) - // if (info.expanded && !info.node.expanded) { - // //let newRoot = _.cloneDeep(root); - // const node = root.findChild(info.node.key as string); - // if (node) { - // node.expandSelf(); - // this.setState({ root: root }); - // } - // } - this.forceUpdate(); - }} - loadData={this.handleOnLoadData.bind(this)} >
- ) : ( - `Work Dir (${workdir}) Empty` - ); + ); } } diff --git a/render-process/index.css b/render-process/index.css index 55ef243..e4161c4 100644 --- a/render-process/index.css +++ b/render-process/index.css @@ -42,10 +42,26 @@ body { background-color: #818181; } -.site-tree-search-value { - color: #f50; -} [data-theme="dark"] .site-tree-search-value { color: #d84a1b; - } \ No newline at end of file + } + + +.explorer-node { + margin: 0; + padding: 0; + line-height: 20px; + white-space: nowrap; + list-style: none; + outline: 0; + color: #ffffff; +} + +.explorer-node-title { + color: #ffffff; +} + +.explorer-node-search-value { + color: #f50; +} diff --git a/render-process/index.tsx b/render-process/index.tsx index 590f99c..3e4ac8c 100644 --- a/render-process/index.tsx +++ b/render-process/index.tsx @@ -5,13 +5,13 @@ import { Layout, message, Tabs } from "antd"; import { ipcRenderer, remote } from "electron"; import * as Utils from "../common/Utils"; import MainEventType from "../common/MainEventType"; -import Properties from "./Properties"; import Settings from "../main-process/Settings"; import "antd/dist/antd.dark.css"; import "./index.css"; import RegisterNode from "./RegisterNode"; import TreeTabs from "./TreeTabs"; +import Explorer from "./Explorer"; const { Sider, Content } = Layout; @@ -82,7 +82,7 @@ export default class Main extends Component { {workdir !== "" ? ( - { this.tabs.openFile(path); diff --git a/webpack.config.js b/webpack.config.js index bd9d1cf..57e463a 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -23,15 +23,16 @@ module.exports = { { test: /\.(jpe?g|png|gif|svg)$/i, loader: "file-loader" }, { enforce: "pre", test: /\.js$/, loader: "source-map-loader" }, { - test: /\.css$/, - loaders: ['style-loader', 'css-loader'] + test: /\.(sass|less|css)$/, + loaders: ['style-loader', 'css-loader', 'less-loader'] }, {//https://github.com/ashtuchkin/iconv-lite/issues/205 test: /node_modules[\/\\](iconv-lite)[\/\\].+/, resolve: { aliasFields: ['main'] } - } + }, + ] },