From c4e3999546b541216748098fc08dd40a8090448a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=B2=81=E6=A0=91=E4=BA=BA?= Date: Sun, 21 May 2023 16:36:21 +0100 Subject: [PATCH] feat: add basic file drag & drop support (#6) --- README.MD | 2 +- package.json | 1 + pnpm-lock.yaml | 30 ++++++++++++++++++++++++++++++ src/SelectFile.tsx | 36 ++++++++++++++++++++++-------------- 4 files changed, 54 insertions(+), 15 deletions(-) diff --git a/README.MD b/README.MD index db09a94..baa6661 100644 --- a/README.MD +++ b/README.MD @@ -72,7 +72,7 @@ pnpm link ../libparakeet-js/npm ## TODO -- [ ] #6 文件拖放 (利用 `react-dropzone`?) +- [x] #6 文件拖放 (利用 `react-dropzone`?) - [ ] 各类算法 [追踪 `crypto` 标签](https://git.unlock-music.dev/um/um-react/issues?labels=67) - [ ] #7 简易元数据编辑器 - [x] ~#8 添加单元测试~ 框架加上了,以后慢慢添加更多测试即可。 diff --git a/package.json b/package.json index b5f6f5b..b2f05d0 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "nanoid": "^4.0.2", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-dropzone": "^14.2.3", "react-promise-suspense": "^0.3.4", "react-redux": "^8.0.5" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 77d34a3..cd021d5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -31,6 +31,9 @@ dependencies: react-dom: specifier: ^18.2.0 version: 18.2.0(react@18.2.0) + react-dropzone: + specifier: ^14.2.3 + version: 14.2.3(react@18.2.0) react-promise-suspense: specifier: ^0.3.4 version: 0.3.4 @@ -2879,6 +2882,12 @@ packages: { integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== } dev: true + /attr-accept@2.2.2: + resolution: + { integrity: sha512-7prDjvt9HmqiZ0cl5CRjtS84sEyhsHP2coDkaZKRKVfCDo9s7iw7ChVmar78Gu9pC4SoR/28wFu/G5JJhTnqEg== } + engines: { node: '>=4' } + dev: false + /available-typed-arrays@1.0.5: resolution: { integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== } @@ -3671,6 +3680,14 @@ packages: flat-cache: 3.0.4 dev: true + /file-selector@0.6.0: + resolution: + { integrity: sha512-QlZ5yJC0VxHxQQsQhXvBaC7VRJ2uaxTf+Tfpu4Z/OcVQJVpZO+DGU0rkoVW5ce2SccxugvpBJoMvUs59iILYdw== } + engines: { node: '>= 12' } + dependencies: + tslib: 2.5.0 + dev: false + /fill-range@7.0.1: resolution: { integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== } @@ -5041,6 +5058,19 @@ packages: react: 18.2.0 scheduler: 0.23.0 + /react-dropzone@14.2.3(react@18.2.0): + resolution: + { integrity: sha512-O3om8I+PkFKbxCukfIR3QAGftYXDZfOE2N1mr/7qebQJHs7U+/RSL/9xomJNpRg9kM5h9soQSdf0Gc7OHF5Fug== } + engines: { node: '>= 10.13' } + peerDependencies: + react: '>= 16.8 || 18.0.0' + dependencies: + attr-accept: 2.2.2 + file-selector: 0.6.0 + prop-types: 15.8.1 + react: 18.2.0 + dev: false + /react-fast-compare@3.2.1: resolution: { integrity: sha512-xTYf9zFim2pEif/Fw16dBiXpe0hoy5PxcD8+OwBnTtNLfIm3g6WxhKNurY+6OmdH1u6Ta/W/Vl6vjbYP1MFnDg== } diff --git a/src/SelectFile.tsx b/src/SelectFile.tsx index df28f78..181c6fe 100644 --- a/src/SelectFile.tsx +++ b/src/SelectFile.tsx @@ -1,21 +1,27 @@ -import React, { useId } from 'react'; - +import { useDropzone } from 'react-dropzone'; import { Box, Text } from '@chakra-ui/react'; import { UnlockIcon } from '@chakra-ui/icons'; + import { useAppDispatch } from './hooks'; import { addNewFile, processFile } from './features/file-listing/fileListingSlice'; import { nanoid } from 'nanoid'; export function SelectFile() { const dispatch = useAppDispatch(); - const id = useId(); + const { getRootProps, getInputProps, isDragActive } = useDropzone({ + multiple: true, + onDropAccepted(files, _event) { + console.debug( + 'react-dropzone/onDropAccepted(%o, %o)', + files.length, + files.map((x) => x.name) + ); - const handleFileSelection = (e: React.ChangeEvent) => { - if (e.target.files) { - for (const file of e.target.files) { + for (const file of files) { const blobURI = URL.createObjectURL(file); const fileName = file.name; const fileId = 'file://' + nanoid(); + // FIXME: this should be a single action/thunk that first adds the item, then updates it. dispatch( addNewFile({ @@ -26,15 +32,12 @@ export function SelectFile() { ); dispatch(processFile({ fileId })); } - } - - e.target.value = ''; - }; + }, + }); return ( + + - {/* 将文件拖到此处,或 */} + 将文件拖到此处,或 点我选择 需要解密的文件 - 仅在浏览器内对文件进行解锁,无需消耗流量