@zjlab-fe/data-hub-ui 0.21.7 → 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/es/assets/cardImg.png.js +3 -0
- package/es/assets/closeBtn.png.js +3 -0
- package/es/assets/icon-tag-header.png.js +3 -0
- package/es/assets/source.png.js +3 -0
- package/es/components/FileUploader/FileUploadModal.js +24 -0
- package/es/components/FileUploader/FileUploader.js +20 -0
- package/es/components/FileUploader/FileUploaderImpl/FileUploader.js +34 -0
- package/es/components/FileUploader/FileUploaderImpl/FileUploaderContextProvider.js +46 -0
- package/es/components/FileUploader/FileUploaderImpl/FileUploaderFileReceiver.css.js +36 -0
- package/es/components/FileUploader/FileUploaderImpl/FileUploaderFileReceiver.js +57 -0
- package/es/components/FileUploader/FileUploaderImpl/FileUploaderFileReceiverContainer.js +24 -0
- package/es/components/FileUploader/FileUploaderImpl/FileUploaderFileReceiverDesc.js +9 -0
- package/es/components/FileUploader/FileUploaderImpl/FileUploaderList.js +46 -0
- package/es/components/FileUploader/FileUploaderImpl/FileUploaderListItem.js +46 -0
- package/es/components/FileUploader/FileUploaderImpl/FileUploaderListItemFail.js +21 -0
- package/es/components/FileUploader/FileUploaderImpl/FileUploaderListItemPaused.js +20 -0
- package/es/components/FileUploader/FileUploaderImpl/FileUploaderListItemUploading.js +43 -0
- package/es/components/FileUploader/FileUploaderImpl/FileUploaderlListItemFinished.js +32 -0
- package/es/components/FileUploader/Locale/translations.js +52 -0
- package/es/components/FileUploader/Locale/useTranslate.js +16 -0
- package/es/components/FileUploader/UploadStoreProvider/UploadStoreProvider.js +31 -0
- package/es/components/FileUploader/UploadStoreProvider/uploadStoreReducer.js +62 -0
- package/es/components/FileUploader/UploadStoreProvider/useOnFileAllUploaded.js +31 -0
- package/es/components/FileUploader/UploadStoreProvider/useSaveUnfinishedUploads.js +42 -0
- package/es/components/FileUploader/UploadStoreProvider/useSetupMergingEvent.js +45 -0
- package/es/components/FileUploader/hooks/useCancelUpload.js +40 -0
- package/es/components/FileUploader/hooks/useCurrentFile.js +61 -0
- package/es/components/FileUploader/hooks/useCurrentFileOnUploading.js +52 -0
- package/es/components/FileUploader/hooks/useCurrentFileSetupAndBackUp.js +39 -0
- package/es/components/FileUploader/hooks/useFormatFiles.js +64 -0
- package/es/components/FileUploader/hooks/useFormatFilesFindDuplicates.js +75 -0
- package/es/components/FileUploader/hooks/useFormatFilesRemoveDuplicates.js +21 -0
- package/es/components/FileUploader/hooks/useHandleChunkCompletion.js +31 -0
- package/es/components/FileUploader/hooks/useOnMounted.js +24 -0
- package/es/components/FileUploader/hooks/useOnMountedResumeUnfinished.js +58 -0
- package/es/components/FileUploader/hooks/useRetryUpload.js +33 -0
- package/es/components/FileUploader/hooks/useUploadChunk.js +46 -0
- package/es/components/FileUploader/icons/CloseFilled.js +7 -0
- package/es/components/FileUploader/icons/UnkownFileIcon.js +7 -0
- package/es/components/FileUploader/icons/UploadIcon.js +7 -0
- package/es/components/FileUploader/index.css.js +532 -0
- package/es/components/FileUploader/index.js +23 -0
- package/es/components/FileUploader/types.js +13 -0
- package/es/components/FileUploader/utils/calcDisplaySize.js +20 -0
- package/es/components/FileUploader/utils/checkExpiryTime.js +15 -0
- package/es/components/FileUploader/utils/createFileToUpload.js +60 -0
- package/es/components/FileUploader/utils/fileDB/addFilesToIndexdb.js +14 -0
- package/es/components/FileUploader/utils/fileDB/deleteFileInStore.js +18 -0
- package/es/components/FileUploader/utils/fileDB/deleteObjectStore.js +25 -0
- package/es/components/FileUploader/utils/fileDB/index.js +77 -0
- package/es/components/FileUploader/utils/fileDB/openDBAndRetrieveData.js +90 -0
- package/es/components/FileUploader/utils/fileDB/retrieveExistingData.js +49 -0
- package/es/components/FileUploader/utils/modalConfig.css.js +20 -0
- package/es/components/FileUploader/utils/modalConfig.js +32 -0
- package/es/components/FileUploader/utils/retrieveAllFiles.js +70 -0
- package/es/components/FileUploader/utils/splitFileIntoChunk.js +15 -0
- package/es/components/SDK-modal/document-link.js +8 -0
- package/es/components/SDK-modal/index.js +25 -0
- package/es/components/SDK-modal/index.module.scss.js +49 -0
- package/es/components/SDK-modal/inner-modal.js +59 -0
- package/es/components/SDK-modal/locale/translations.js +17 -0
- package/es/components/apply-perm-modal/index.js +53 -0
- package/es/components/apply-perm-modal/index.module.scss.js +96 -0
- package/es/components/auth-tag/index.js +23 -0
- package/es/components/bench-card/index.js +20 -0
- package/es/components/bench-card/index.module.scss.js +48 -0
- package/es/components/confirm-again/index.js +15 -0
- package/es/components/confirm-again/index.scss.js +37 -0
- package/es/components/copy/index.js +41 -0
- package/es/components/copy/index.module.scss.js +15 -0
- package/es/components/corpus-card/index.js +88 -0
- package/es/components/corpus-card/index.module.scss.js +171 -0
- package/es/components/feature-card/classNames.js +72 -0
- package/es/components/feature-card/components.js +48 -0
- package/es/components/feature-card/context.js +13 -0
- package/es/components/feature-card/index.css.js +655 -0
- package/es/components/feature-card/index.js +48 -0
- package/es/components/file-preview/data-table/index.js +94 -0
- package/es/components/file-preview/data-table/index.module.scss.js +54 -0
- package/es/components/file-preview/excel-preview/index.js +132 -0
- package/es/components/file-preview/excel-preview/index.module.scss.js +11 -0
- package/es/components/file-preview/excel-preview/utils.js +46 -0
- package/es/components/file-preview/img-preview/index.js +18 -0
- package/es/components/file-preview/img-preview/index.module.scss.js +17 -0
- package/es/components/file-preview/index.js +124 -0
- package/es/components/file-preview/index.module.scss.js +32 -0
- package/es/components/file-preview/json-preview/index.js +166 -0
- package/es/components/file-preview/markdown-preview/index.js +53 -0
- package/es/components/file-preview/markdown-preview/index.module.scss.js +1055 -0
- package/es/components/file-preview/parquet-preview/index.js +54 -0
- package/es/components/file-preview/pdf-preview/index.js +215 -0
- package/es/components/file-preview/pdf-preview/index.module.scss.js +16 -0
- package/es/components/file-preview/table-preview/index.js +43 -0
- package/es/components/file-preview/table-preview/index.module.scss.js +11 -0
- package/es/components/file-preview/txt-preview/index.js +24 -0
- package/es/components/file-preview/util.js +94 -0
- package/es/components/file-uploader/components/circle-progress.css.js +39 -0
- package/es/components/file-uploader/components/circle-progress.js +12 -0
- package/es/components/file-uploader/components/hooks/use-drop-zone.js +74 -0
- package/es/components/file-uploader/components/hooks/use-file-validation.js +52 -0
- package/es/components/file-uploader/components/icons.js +19 -0
- package/es/components/file-uploader/components/theme.css.js +64 -0
- package/es/components/file-uploader/components/uploader-drop-zone.css.js +66 -0
- package/es/components/file-uploader/components/uploader-drop-zone.js +74 -0
- package/es/components/file-uploader/components/uploader-file-item.css.js +186 -0
- package/es/components/file-uploader/components/uploader-file-item.js +63 -0
- package/es/components/file-uploader/components/uploader-file-list.css.js +43 -0
- package/es/components/file-uploader/components/uploader-file-list.js +27 -0
- package/es/components/file-uploader/components/uploader.css.js +20 -0
- package/es/components/file-uploader/components/uploader.js +51 -0
- package/es/components/file-uploader/components/uploading-status.css.js +52 -0
- package/es/components/file-uploader/components/uploading-status.js +54 -0
- package/es/components/file-uploader/components/utils/directory-reader.js +65 -0
- package/es/components/file-uploader/constants.js +31 -0
- package/es/components/file-uploader/context/action-registry.js +69 -0
- package/es/components/file-uploader/context/file-state-store.js +83 -0
- package/es/components/file-uploader/context/handler-registry.js +119 -0
- package/es/components/file-uploader/context/upload-context.js +36 -0
- package/es/components/file-uploader/context/upload-provider.js +77 -0
- package/es/components/file-uploader/context/upload-reducer.js +21 -0
- package/es/components/file-uploader/context/use-upload-engine.js +440 -0
- package/es/components/file-uploader/engine/queue-callbacks.js +257 -0
- package/es/components/file-uploader/engine/queue-manager.js +195 -0
- package/es/components/file-uploader/engine/queue-uploader.js +25 -0
- package/es/components/file-uploader/hooks/use-upload.js +327 -0
- package/es/components/file-uploader/utils/chunk-handlers.js +66 -0
- package/es/components/file-uploader/utils/ensure-handlers.js +53 -0
- package/es/components/file-uploader/utils/error-handler.js +84 -0
- package/es/components/file-uploader/utils/upload-controllers.js +43 -0
- package/es/components/file-uploader/utils/upload-handler.js +68 -0
- package/es/components/file-uploader/utils/validate-handlers.js +16 -0
- package/es/components/floating-label-input/index.js +46 -0
- package/es/components/floating-label-input/index.module.scss.js +30 -0
- package/es/components/floating-layer/index.js +15 -0
- package/es/components/floating-layer/index.scss.js +31 -0
- package/es/components/header/index.js +10 -0
- package/es/components/header/index.module.scss.js +16 -0
- package/es/components/input-tag/index.js +65 -0
- package/es/components/menu/index.js +96 -0
- package/es/components/menu/index.module.scss.js +188 -0
- package/es/components/model-card/index.js +20 -0
- package/es/components/model-card/index.module.scss.js +116 -0
- package/es/components/notion-editor/code-block/index.js +18 -0
- package/es/components/notion-editor/code-block/languageDetector.js +134 -0
- package/es/components/notion-editor/code-block/languages.js +42 -0
- package/es/components/notion-editor/index.js +258 -0
- package/es/components/notion-editor/index.scss.js +421 -0
- package/es/components/notion-editor/parseMarkdown.js +184 -0
- package/es/components/operator-chain/components/AddButton.js +20 -0
- package/es/components/operator-chain/components/IOCard.js +8 -0
- package/es/components/operator-chain/components/SingleCard.js +12 -0
- package/es/components/operator-chain/components/VirtualDropdown.js +56 -0
- package/es/components/operator-chain/index.js +83 -0
- package/es/components/operator-chain/index.module.scss.js +232 -0
- package/es/components/permission-editor/index.js +9 -0
- package/es/components/permission-editor/permissionEditModal/index.js +37 -0
- package/es/components/permission-editor/permissionEditor/index.js +253 -0
- package/es/components/permission-editor/permissionEditor/index.module.scss.js +22 -0
- package/es/components/permission-editor/permissionViewPopover/index.js +9 -0
- package/es/components/popover-select/index.js +42 -0
- package/es/components/popover-select/index.module.scss.js +22 -0
- package/es/components/radio-card/index.js +24 -0
- package/es/components/radio-card/index.scss.js +58 -0
- package/es/components/section-heading/classNames.js +22 -0
- package/es/components/section-heading/components.js +27 -0
- package/es/components/section-heading/context.js +13 -0
- package/es/components/section-heading/index.css.js +648 -0
- package/es/components/section-heading/index.js +37 -0
- package/es/components/status-tag/index.js +31 -0
- package/es/components/tag-group-filter/dataSizeFilter.js +100 -0
- package/es/components/tag-group-filter/index.js +53 -0
- package/es/components/tag-group-filter/index.module.scss.js +134 -0
- package/es/components/tag-group-filter/tagFilter.js +19 -0
- package/es/components/tag-view/index.js +138 -0
- package/es/components/tag-view/index.module.scss.js +56 -0
- package/es/components/tag-view/useSize.js +41 -0
- package/es/components/tip-tap/bubble-menu.js +47 -0
- package/es/components/tip-tap/editor.js +34 -0
- package/es/components/tip-tap/extensions/index.js +133 -0
- package/es/components/tip-tap/extensions/markdown-paste.js +148 -0
- package/es/components/tip-tap/icons/index.js +29 -0
- package/es/components/tip-tap/reader.js +15 -0
- package/es/components/tip-tap/styles/editor.css.js +863 -0
- package/es/components/tip-tap/toolbar/components/color-picker.js +76 -0
- package/es/components/tip-tap/toolbar/components/heading-dropdown.js +44 -0
- package/es/components/tip-tap/toolbar/components/image-button.js +26 -0
- package/es/components/tip-tap/toolbar/components/link-button.js +107 -0
- package/es/components/tip-tap/toolbar/components/table-button.js +37 -0
- package/es/components/tip-tap/toolbar/components/toolbar-button.js +7 -0
- package/es/components/tip-tap/toolbar/index.js +39 -0
- package/es/components/uploadDrawer/UploadStoreProvider.js +61 -0
- package/es/components/uploadDrawer/fileUploadDrawer.js +66 -0
- package/es/components/uploadDrawer/fileUploadDrawerFileDragger.js +71 -0
- package/es/components/uploadDrawer/fileUploadDrawerList.js +54 -0
- package/es/components/uploadDrawer/fileUploadDrawerListProgressButton.js +54 -0
- package/es/components/uploadDrawer/hooks/useCancelUpload.js +37 -0
- package/es/components/uploadDrawer/hooks/useFilterFiles.js +107 -0
- package/es/components/uploadDrawer/hooks/useFinishUpload.js +33 -0
- package/es/components/uploadDrawer/hooks/useFormatFiles.js +54 -0
- package/es/components/uploadDrawer/hooks/useProgressButtonRef.js +22 -0
- package/es/components/uploadDrawer/hooks/useRemoveFilesInUploadQueue.js +21 -0
- package/es/components/uploadDrawer/hooks/useResumeUnfinishedUploads.js +52 -0
- package/es/components/uploadDrawer/hooks/useRetryUpload.js +35 -0
- package/es/components/uploadDrawer/hooks/useSaveUnfinishedUploads.js +42 -0
- package/es/components/uploadDrawer/hooks/useSetupUpload.js +80 -0
- package/es/components/uploadDrawer/hooks/useUploadFileToOSS.js +23 -0
- package/es/components/uploadDrawer/index.css.js +511 -0
- package/es/components/uploadDrawer/index.js +43 -0
- package/es/components/uploadDrawer/utils/calcDisplaySize.js +19 -0
- package/es/components/uploadDrawer/utils/constant.js +16 -0
- package/es/components/uploadDrawer/utils/createFileToUpload.js +51 -0
- package/es/components/uploadDrawer/utils/fileDB/deleteFileInStore.js +28 -0
- package/es/components/uploadDrawer/utils/fileDB/deleteObjectStore.js +28 -0
- package/es/components/uploadDrawer/utils/fileDB/handleAddFilesToDB.js +37 -0
- package/es/components/uploadDrawer/utils/fileDB/index.js +9 -0
- package/es/components/uploadDrawer/utils/fileDB/openDB.js +111 -0
- package/es/components/uploadDrawer/utils/retrieveAllFiles.js +110 -0
- package/es/components/uploadDrawer/utils/shouldCreateNewFile.js +13 -0
- package/es/components/uploadDrawer/utils/splitFileIntoChunk.js +15 -0
- package/es/index.js +42 -1
- package/es/lib/utils.js +8 -0
- package/lib/index.js +1 -1
- package/package.json +164 -154
- package/rollup.es.config.mjs +177 -0
- package/tsconfig.rollup.json +7 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
const localeEn = {
|
|
2
|
+
'FileUploader 必须在 UploadStoreProvider 内使用': 'FileUploader must be used within UploadStoreProvider',
|
|
3
|
+
'FileUploadModal 必须在 UploadStoreProvider 内使用': 'FileUploadModal must be used within UploadStoreProvider',
|
|
4
|
+
文件上传: 'File Upload',
|
|
5
|
+
确定: 'Confirm',
|
|
6
|
+
等待上传: 'Waiting for upload',
|
|
7
|
+
已取消: 'Cancelled',
|
|
8
|
+
上传中: 'Uploading',
|
|
9
|
+
上传失败: 'Upload failed',
|
|
10
|
+
已上传: 'Uploaded',
|
|
11
|
+
分块合并中: 'Merging parts',
|
|
12
|
+
以下文件大小超过: 'The following files exceed the size',
|
|
13
|
+
已删除: 'Deleted',
|
|
14
|
+
点击或拖拽上传文件: 'Click or drag to upload files',
|
|
15
|
+
'发现同名文件,是否覆盖?': 'Duplicate file found, overwrite?',
|
|
16
|
+
覆盖: 'Overwrite',
|
|
17
|
+
取消: 'Cancel',
|
|
18
|
+
正在上传: 'Uploading',
|
|
19
|
+
取消失败: 'Cancel failed',
|
|
20
|
+
当前上传: 'Current Upload',
|
|
21
|
+
已暂停: 'Paused',
|
|
22
|
+
上传成功: 'Upload successful',
|
|
23
|
+
校验中: 'Calibrating',
|
|
24
|
+
合并中: 'Merging',
|
|
25
|
+
};
|
|
26
|
+
const localeZh = {
|
|
27
|
+
'FileUploader 必须在 UploadStoreProvider 内使用': 'FileUploader 必须在 UploadStoreProvider 内使用',
|
|
28
|
+
'FileUploadModal 必须在 UploadStoreProvider 内使用': 'FileUploadModal 必须在 UploadStoreProvider 内使用',
|
|
29
|
+
文件上传: '文件上传',
|
|
30
|
+
确定: '确定',
|
|
31
|
+
等待上传: '等待上传',
|
|
32
|
+
已取消: '已取消',
|
|
33
|
+
上传中: '上传中',
|
|
34
|
+
上传失败: '上传失败',
|
|
35
|
+
已上传: '已上传',
|
|
36
|
+
分块合并中: '分块合并中',
|
|
37
|
+
以下文件大小超过: '以下文件大小超过',
|
|
38
|
+
已删除: '已删除',
|
|
39
|
+
点击或拖拽上传文件: '点击或拖拽上传文件',
|
|
40
|
+
'发现同名文件,是否覆盖?': '发现同名文件,是否覆盖?',
|
|
41
|
+
覆盖: '覆盖',
|
|
42
|
+
取消: '取消',
|
|
43
|
+
正在上传: '正在上传',
|
|
44
|
+
取消失败: '取消失败',
|
|
45
|
+
当前上传: '当前上传',
|
|
46
|
+
已暂停: '已暂停',
|
|
47
|
+
上传成功: '上传成功',
|
|
48
|
+
校验中: '校验中',
|
|
49
|
+
合并中: '合并中',
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export { localeEn, localeZh };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { useContext, useCallback } from 'react';
|
|
2
|
+
import { FileUploaderLocaleContext } from '../UploadStoreProvider/UploadStoreProvider.js';
|
|
3
|
+
|
|
4
|
+
function useTranslate() {
|
|
5
|
+
const locale = useContext(FileUploaderLocaleContext);
|
|
6
|
+
return useCallback((key) => {
|
|
7
|
+
const content = locale[key];
|
|
8
|
+
if (!content) {
|
|
9
|
+
console.warn(`Translation key not found: ${key}`);
|
|
10
|
+
return key;
|
|
11
|
+
}
|
|
12
|
+
return content;
|
|
13
|
+
}, [locale]);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export { useTranslate };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { createContext, useReducer, useState } from 'react';
|
|
3
|
+
import { useSaveUnfinishedUploads } from './useSaveUnfinishedUploads.js';
|
|
4
|
+
import { localeZh, localeEn } from '../Locale/translations.js';
|
|
5
|
+
import { useSetupMergingEvent } from './useSetupMergingEvent.js';
|
|
6
|
+
import { useOnFileAllUploaded } from './useOnFileAllUploaded.js';
|
|
7
|
+
import { uploadReducer } from './uploadStoreReducer.js';
|
|
8
|
+
|
|
9
|
+
const FileUploaderLocaleContext = createContext(localeZh);
|
|
10
|
+
const AllUploaderManagersContext = createContext({});
|
|
11
|
+
const AllUploaderManagersDispatchContext = createContext(() => null);
|
|
12
|
+
const AllOnUploadSuccessesContext = createContext({});
|
|
13
|
+
const AllOnUploadSuccessesDispatchContext = createContext(() => null);
|
|
14
|
+
const TEMP_STORE = {};
|
|
15
|
+
const UploadStoreContext = createContext(TEMP_STORE);
|
|
16
|
+
const UploadStoreDispatchContext = createContext(() => null);
|
|
17
|
+
/**
|
|
18
|
+
* @deprecated This component is deprecated and will be removed in future releases.
|
|
19
|
+
*/
|
|
20
|
+
function UploadStoreProvider({ locale = 'zh', children, }) {
|
|
21
|
+
const FileUploaderLocale = locale === 'zh' ? localeZh : localeEn;
|
|
22
|
+
const [uploadStore, setUploadStore] = useReducer(uploadReducer, {});
|
|
23
|
+
const [allUploaderManagers, setAllUploaderManagers] = useState({});
|
|
24
|
+
const [allOnUploadSuccesses, setAllOnUploadSuccesses] = useState({});
|
|
25
|
+
useSaveUnfinishedUploads(uploadStore);
|
|
26
|
+
useOnFileAllUploaded(uploadStore, setUploadStore);
|
|
27
|
+
useSetupMergingEvent(uploadStore, allUploaderManagers, allOnUploadSuccesses, setUploadStore);
|
|
28
|
+
return (jsx(FileUploaderLocaleContext.Provider, { value: FileUploaderLocale, children: jsx(AllUploaderManagersContext.Provider, { value: allUploaderManagers, children: jsx(AllUploaderManagersDispatchContext.Provider, { value: setAllUploaderManagers, children: jsx(AllOnUploadSuccessesContext.Provider, { value: allOnUploadSuccesses, children: jsx(AllOnUploadSuccessesDispatchContext.Provider, { value: setAllOnUploadSuccesses, children: jsx(UploadStoreContext.Provider, { value: uploadStore, children: jsx(UploadStoreDispatchContext.Provider, { value: setUploadStore, children: children }) }) }) }) }) }) }));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export { AllOnUploadSuccessesContext, AllOnUploadSuccessesDispatchContext, AllUploaderManagersContext, AllUploaderManagersDispatchContext, FileUploaderLocaleContext, TEMP_STORE, UploadStoreContext, UploadStoreDispatchContext, UploadStoreProvider as default };
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { FILE_UPLOAD_STATUS } from '../types.js';
|
|
2
|
+
|
|
3
|
+
function uploadReducer(uploads, action) {
|
|
4
|
+
switch (action.type) {
|
|
5
|
+
case 'add': {
|
|
6
|
+
return Object.assign(Object.assign({}, uploads), { [action.identifier]: [] });
|
|
7
|
+
}
|
|
8
|
+
case 'remove_file': {
|
|
9
|
+
const fileList = uploads[action.identifier];
|
|
10
|
+
const fileIndex = fileList.findIndex((p) => p.fileName === action.fileName);
|
|
11
|
+
return Object.assign(Object.assign({}, uploads), { [action.identifier]: [...fileList.slice(0, fileIndex), ...fileList.slice(fileIndex + 1)] });
|
|
12
|
+
}
|
|
13
|
+
case 'edit_file': {
|
|
14
|
+
const fileList = uploads[action.identifier];
|
|
15
|
+
const fileIndex = fileList.findIndex((p) => p.fileName === action.file.fileName);
|
|
16
|
+
return Object.assign(Object.assign({}, uploads), { [action.identifier]: [...fileList.slice(0, fileIndex), action.file, ...fileList.slice(fileIndex + 1)] });
|
|
17
|
+
}
|
|
18
|
+
case 'add_file': {
|
|
19
|
+
const fileList = uploads[action.identifier];
|
|
20
|
+
const fileIndex = fileList.findIndex((p) => p.fileName === action.file.fileName);
|
|
21
|
+
if (fileIndex === -1) {
|
|
22
|
+
return Object.assign(Object.assign({}, uploads), { [action.identifier]: [...fileList, action.file] });
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
return Object.assign(Object.assign({}, uploads), { [action.identifier]: [
|
|
26
|
+
...fileList.slice(0, fileIndex),
|
|
27
|
+
action.file,
|
|
28
|
+
...fileList.slice(fileIndex + 1),
|
|
29
|
+
] });
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
case 'add_files': {
|
|
33
|
+
const fileList = uploads[action.identifier];
|
|
34
|
+
return Object.assign(Object.assign({}, uploads), { [action.identifier]: [...fileList, ...action.files] });
|
|
35
|
+
}
|
|
36
|
+
case 'clear_finished': {
|
|
37
|
+
const fileList = uploads[action.identifier];
|
|
38
|
+
return Object.assign(Object.assign({}, uploads), { [action.identifier]: fileList.filter((f) => f.fileStatus !== FILE_UPLOAD_STATUS.FINISHED) });
|
|
39
|
+
}
|
|
40
|
+
case 'edit_files': {
|
|
41
|
+
const updatedFiles = Object.entries(action.files).reduce((acc, [identifier, files]) => {
|
|
42
|
+
const fileList = uploads[identifier];
|
|
43
|
+
files.forEach((file) => {
|
|
44
|
+
const fileIndex = fileList.findIndex((p) => p.fileName === file.fileName);
|
|
45
|
+
if (fileIndex !== -1) {
|
|
46
|
+
fileList[fileIndex] = file;
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
fileList.push(file);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
return acc;
|
|
53
|
+
}, Object.assign({}, uploads));
|
|
54
|
+
return updatedFiles;
|
|
55
|
+
}
|
|
56
|
+
default: {
|
|
57
|
+
throw Error('Unknown action');
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export { uploadReducer };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
import { FILE_UPLOAD_STATUS } from '../types.js';
|
|
3
|
+
|
|
4
|
+
function useOnFileAllUploaded(uploadStore, setUploadStore) {
|
|
5
|
+
useEffect(() => {
|
|
6
|
+
const identifiers = Object.keys(uploadStore);
|
|
7
|
+
const allEditFiles = identifiers.reduce((acc, identifier) => {
|
|
8
|
+
const store = uploadStore[identifier];
|
|
9
|
+
const allUploadedFile = store.filter((file) => file.fileStatus === FILE_UPLOAD_STATUS.ALL_UPLOADED);
|
|
10
|
+
const successfulUploads = allUploadedFile.filter((file) => file.failSeq.length === 0);
|
|
11
|
+
const failedUploads = allUploadedFile.filter((file) => file.failSeq.length > 0);
|
|
12
|
+
const uploadingFile = store.find((file) => file.fileStatus === FILE_UPLOAD_STATUS.UPLOADING);
|
|
13
|
+
const initFile = store.find((file) => file.fileStatus === FILE_UPLOAD_STATUS.INIT);
|
|
14
|
+
const shouldUploadFile = uploadingFile ? undefined : initFile;
|
|
15
|
+
const editFiles = [
|
|
16
|
+
...failedUploads.map((file) => (Object.assign(Object.assign({}, file), { fileStatus: FILE_UPLOAD_STATUS.FAILED }))),
|
|
17
|
+
...successfulUploads.map((file) => (Object.assign(Object.assign({}, file), { fileStatus: FILE_UPLOAD_STATUS.MERGING }))),
|
|
18
|
+
shouldUploadFile ? Object.assign(Object.assign({}, shouldUploadFile), { fileStatus: FILE_UPLOAD_STATUS.UPLOADING }) : undefined,
|
|
19
|
+
].filter((f) => !!f);
|
|
20
|
+
if (editFiles.length) {
|
|
21
|
+
return Object.assign(Object.assign({}, acc), { [identifier]: editFiles });
|
|
22
|
+
}
|
|
23
|
+
return acc;
|
|
24
|
+
}, {});
|
|
25
|
+
if (Object.keys(allEditFiles).length) {
|
|
26
|
+
setUploadStore({ type: 'edit_files', files: allEditFiles });
|
|
27
|
+
}
|
|
28
|
+
}, [setUploadStore, uploadStore]);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export { useOnFileAllUploaded };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { __rest } from 'tslib';
|
|
2
|
+
import { useEffect } from 'react';
|
|
3
|
+
import '../utils/checkExpiryTime.js';
|
|
4
|
+
import { FILE_UPLOAD_STATUS } from '../types.js';
|
|
5
|
+
import { deleteObjectStore } from '../utils/fileDB/deleteObjectStore.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 未完成任务信息存储在localStorage而不是indexdb中,需要分别处理
|
|
9
|
+
* 因为之前的测试中发现,indexdb的存储方式在某些浏览器中会丢失数据
|
|
10
|
+
* 所以需要将未完成任务信息存储在localStorage中
|
|
11
|
+
*
|
|
12
|
+
* TODO: 将未完成任务信息存储在indexdb中
|
|
13
|
+
*/
|
|
14
|
+
function useSaveUnfinishedUploads(uploadStore) {
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
window.addEventListener('beforeunload', saveUnfinishedUploads);
|
|
17
|
+
return () => {
|
|
18
|
+
window.removeEventListener('beforeunload', saveUnfinishedUploads);
|
|
19
|
+
};
|
|
20
|
+
function saveUnfinishedUploads() {
|
|
21
|
+
Object.entries(uploadStore).forEach(([key, uploads]) => {
|
|
22
|
+
const unfinishedUploads = uploads.filter((upload) => upload.fileStatus !== FILE_UPLOAD_STATUS.FINISHED);
|
|
23
|
+
if (unfinishedUploads.length) {
|
|
24
|
+
localStorage.setItem(key, formatUnfinishedUploads(unfinishedUploads));
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
deleteObjectStore(key);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
}, [uploadStore]);
|
|
32
|
+
}
|
|
33
|
+
function formatUnfinishedUploads(uploads) {
|
|
34
|
+
const formattedUploads = uploads.map((_a) => {
|
|
35
|
+
var { raw: _raw } = _a, uploadInfo = __rest(_a, ["raw"]);
|
|
36
|
+
const { uploadUrls, failSeq } = uploadInfo;
|
|
37
|
+
return Object.assign(Object.assign({}, uploadInfo), { failSeq: [], cancelControllers: {}, uploadUrls: [...uploadUrls, ...failSeq] });
|
|
38
|
+
});
|
|
39
|
+
return JSON.stringify(formattedUploads);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export { formatUnfinishedUploads, useSaveUnfinishedUploads };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { __awaiter } from 'tslib';
|
|
2
|
+
import { useRef, useCallback, useEffect } from 'react';
|
|
3
|
+
import { FILE_UPLOAD_STATUS } from '../types.js';
|
|
4
|
+
|
|
5
|
+
function useSetupMergingEvent(uploadStore, allUploaderManagers, allOnUploadSuccesses, setUploadStore) {
|
|
6
|
+
/**
|
|
7
|
+
* 记录每个 identifier 中正在合并的 uploadId, 防止重复调用 handleAllUploaded
|
|
8
|
+
*/
|
|
9
|
+
const allCurrentlyInMergingUpload = useRef({});
|
|
10
|
+
const handleAllUploaded = useCallback(function handleAllUploaded(identifier, mergingFiles) {
|
|
11
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
12
|
+
const { onAllPartDone } = allUploaderManagers[identifier];
|
|
13
|
+
const onUploadSuccess = allOnUploadSuccesses[identifier];
|
|
14
|
+
const finishedOrFailedFiles = yield Promise.all(mergingFiles.map((file) => __awaiter(this, void 0, void 0, function* () {
|
|
15
|
+
const result = yield onAllPartDone(file.fileName, file.uploadId);
|
|
16
|
+
if (!result.status) {
|
|
17
|
+
return Object.assign(Object.assign({}, file), { fileStatus: FILE_UPLOAD_STATUS.FAILED });
|
|
18
|
+
}
|
|
19
|
+
onUploadSuccess === null || onUploadSuccess === void 0 ? void 0 : onUploadSuccess(file);
|
|
20
|
+
allCurrentlyInMergingUpload.current[identifier].delete(file.uploadId);
|
|
21
|
+
return Object.assign(Object.assign({}, file), { percentage: 100, fileStatus: FILE_UPLOAD_STATUS.FINISHED });
|
|
22
|
+
})));
|
|
23
|
+
setUploadStore({
|
|
24
|
+
type: 'edit_files',
|
|
25
|
+
files: { [identifier]: finishedOrFailedFiles },
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
}, [allUploaderManagers, allOnUploadSuccesses, setUploadStore]);
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
const identifiers = Object.keys(uploadStore);
|
|
31
|
+
identifiers.forEach((identifier) => {
|
|
32
|
+
const store = uploadStore[identifier];
|
|
33
|
+
const mergingFiles = store.filter((file) => file.fileStatus === FILE_UPLOAD_STATUS.MERGING);
|
|
34
|
+
if (mergingFiles.length > 0) {
|
|
35
|
+
const currentlyInMergingUpload = allCurrentlyInMergingUpload.current[identifier] || new Set();
|
|
36
|
+
const newMergingUploads = mergingFiles.filter((file) => !currentlyInMergingUpload.has(file.uploadId));
|
|
37
|
+
newMergingUploads.forEach((file) => currentlyInMergingUpload.add(file.uploadId));
|
|
38
|
+
allCurrentlyInMergingUpload.current[identifier] = currentlyInMergingUpload;
|
|
39
|
+
handleAllUploaded(identifier, newMergingUploads);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
}, [uploadStore, handleAllUploaded]);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export { useSetupMergingEvent };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { __awaiter } from 'tslib';
|
|
2
|
+
import { App } from 'antd';
|
|
3
|
+
import { useContext } from 'react';
|
|
4
|
+
import { AllUploaderManagersContext, UploadStoreDispatchContext } from '../UploadStoreProvider/UploadStoreProvider.js';
|
|
5
|
+
import '../utils/checkExpiryTime.js';
|
|
6
|
+
import '../types.js';
|
|
7
|
+
import { deleteFileInStore } from '../utils/fileDB/deleteFileInStore.js';
|
|
8
|
+
import { IdentifierContext } from '../FileUploaderImpl/FileUploaderContextProvider.js';
|
|
9
|
+
import { useTranslate } from '../Locale/useTranslate.js';
|
|
10
|
+
|
|
11
|
+
function useCancelUpload() {
|
|
12
|
+
const t = useTranslate();
|
|
13
|
+
const { message } = App.useApp();
|
|
14
|
+
const identifier = useContext(IdentifierContext);
|
|
15
|
+
const allUploaderManagers = useContext(AllUploaderManagersContext);
|
|
16
|
+
const setUploadStore = useContext(UploadStoreDispatchContext);
|
|
17
|
+
return function cancelUpload(file) {
|
|
18
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
19
|
+
const { onCancelUpload } = allUploaderManagers[identifier];
|
|
20
|
+
// 没有上传id,说明getUploadUrls失败,则直接删除文件
|
|
21
|
+
if (!file.uploadId) {
|
|
22
|
+
deleteFile(file.fileName);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const result = yield onCancelUpload(file.fileName, file.uploadId);
|
|
26
|
+
if (result.status) {
|
|
27
|
+
deleteFile(file.fileName);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
message.error(result.reason || t('取消失败'));
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
function deleteFile(fileName) {
|
|
35
|
+
deleteFileInStore(String(identifier), fileName);
|
|
36
|
+
setUploadStore({ type: 'remove_file', identifier, fileName });
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export { useCancelUpload };
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { atom, useAtom } from 'jotai';
|
|
2
|
+
import { useRef, useContext, useEffect } from 'react';
|
|
3
|
+
import '../utils/checkExpiryTime.js';
|
|
4
|
+
import 'tslib';
|
|
5
|
+
import { FILE_UPLOAD_STATUS } from '../types.js';
|
|
6
|
+
import { splitFileIntoChunk } from '../utils/splitFileIntoChunk.js';
|
|
7
|
+
import { useCurrentFileOnUploading } from './useCurrentFileOnUploading.js';
|
|
8
|
+
import { IdentifierContext } from '../FileUploaderImpl/FileUploaderContextProvider.js';
|
|
9
|
+
import { useCurrentFileSetupAndBackUp } from './useCurrentFileSetupAndBackUp.js';
|
|
10
|
+
import { UploadStoreDispatchContext } from '../UploadStoreProvider/UploadStoreProvider.js';
|
|
11
|
+
|
|
12
|
+
const currentFileAtom = atom(null);
|
|
13
|
+
const currentFileNameAtom = atom((get) => { var _a; return (_a = get(currentFileAtom)) === null || _a === void 0 ? void 0 : _a.fileName; });
|
|
14
|
+
atom((get) => { var _a; return (_a = get(currentFileAtom)) === null || _a === void 0 ? void 0 : _a.expiryTime; });
|
|
15
|
+
const currentFileUploadIdAtom = atom((get) => { var _a; return (_a = get(currentFileAtom)) === null || _a === void 0 ? void 0 : _a.uploadId; });
|
|
16
|
+
atom((get) => { var _a; return (_a = get(currentFileAtom)) === null || _a === void 0 ? void 0 : _a.raw; });
|
|
17
|
+
const currentFilePercentageAtom = atom((get) => { var _a; return (_a = get(currentFileAtom)) === null || _a === void 0 ? void 0 : _a.percentage; });
|
|
18
|
+
const currentFileCancelControllersAtom = atom((get) => { var _a; return (_a = get(currentFileAtom)) === null || _a === void 0 ? void 0 : _a.cancelControllers; });
|
|
19
|
+
function useCurrentFile() {
|
|
20
|
+
const isUploading = useRef(false);
|
|
21
|
+
const chunks = useRef([]);
|
|
22
|
+
const identifier = useContext(IdentifierContext);
|
|
23
|
+
const [currentFile, setCurrentFile] = useAtom(currentFileAtom);
|
|
24
|
+
const setUploadsStore = useContext(UploadStoreDispatchContext);
|
|
25
|
+
useCurrentFileSetupAndBackUp();
|
|
26
|
+
const onUploading = useCurrentFileOnUploading();
|
|
27
|
+
/**
|
|
28
|
+
* 为了实现当路由变更时仍然能够完成上传
|
|
29
|
+
* 当文件上传状态变为 ALL_UPLOADED 时,将转移到 uploadStore
|
|
30
|
+
* 剩下的工作将在 uploadStore 中完成
|
|
31
|
+
*/
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
if (!currentFile) {
|
|
34
|
+
isUploading.current = false;
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
if (currentFile.fileStatus === FILE_UPLOAD_STATUS.INIT) {
|
|
38
|
+
chunks.current = splitFileIntoChunk(currentFile);
|
|
39
|
+
setCurrentFile((prev) => {
|
|
40
|
+
if (!prev)
|
|
41
|
+
return prev;
|
|
42
|
+
return Object.assign(Object.assign({}, prev), { fileStatus: FILE_UPLOAD_STATUS.UPLOADING, cancelControllers: new Array(chunks.current.length).fill(new AbortController()) });
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
if (currentFile.fileStatus === FILE_UPLOAD_STATUS.UPLOADING && !isUploading.current) {
|
|
46
|
+
isUploading.current = true;
|
|
47
|
+
onUploading(chunks.current);
|
|
48
|
+
}
|
|
49
|
+
if (currentFile.fileStatus === FILE_UPLOAD_STATUS.CANCELED) {
|
|
50
|
+
Object.values(currentFile.cancelControllers).forEach((cc) => cc.abort());
|
|
51
|
+
setUploadsStore({ type: 'remove_file', identifier, fileName: currentFile.fileName });
|
|
52
|
+
setCurrentFile(null);
|
|
53
|
+
}
|
|
54
|
+
if (currentFile.fileStatus === FILE_UPLOAD_STATUS.FAILED) {
|
|
55
|
+
setUploadsStore({ type: 'edit_file', identifier, file: currentFile });
|
|
56
|
+
setCurrentFile(null);
|
|
57
|
+
}
|
|
58
|
+
}, [currentFile, identifier, onUploading, setCurrentFile, setUploadsStore]);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export { currentFileAtom, currentFileCancelControllersAtom, currentFileNameAtom, currentFilePercentageAtom, currentFileUploadIdAtom, useCurrentFile };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { __awaiter } from 'tslib';
|
|
2
|
+
import { useSetAtom } from 'jotai';
|
|
3
|
+
import { useContext, useCallback } from 'react';
|
|
4
|
+
import { FILE_UPLOAD_STATUS } from '../types.js';
|
|
5
|
+
import { currentFileAtom } from './useCurrentFile.js';
|
|
6
|
+
import { UploadStoreDispatchContext } from '../UploadStoreProvider/UploadStoreProvider.js';
|
|
7
|
+
import { IdentifierContext } from '../FileUploaderImpl/FileUploaderContextProvider.js';
|
|
8
|
+
import { useUploadChunk } from './useUploadChunk.js';
|
|
9
|
+
import { useHandleChunkCompletion } from './useHandleChunkCompletion.js';
|
|
10
|
+
|
|
11
|
+
function useCurrentFileOnUploading() {
|
|
12
|
+
const identifier = useContext(IdentifierContext);
|
|
13
|
+
const setCurrentFile = useSetAtom(currentFileAtom);
|
|
14
|
+
const setUploadStore = useContext(UploadStoreDispatchContext);
|
|
15
|
+
const uploadChunk = useUploadChunk();
|
|
16
|
+
const handleChunkCompletion = useHandleChunkCompletion(identifier);
|
|
17
|
+
const putChunk = useCallback((urlInfo, chunk) => __awaiter(this, void 0, void 0, function* () {
|
|
18
|
+
try {
|
|
19
|
+
yield uploadChunk(urlInfo, chunk);
|
|
20
|
+
yield handleChunkCompletion(urlInfo);
|
|
21
|
+
}
|
|
22
|
+
catch (e) {
|
|
23
|
+
if (e instanceof Error && e.message === 'canceled') {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
setCurrentFile((prev) => {
|
|
27
|
+
if (!prev)
|
|
28
|
+
return prev;
|
|
29
|
+
return Object.assign(Object.assign({}, prev), { failSeq: [...prev.failSeq, urlInfo], uploadUrls: prev.uploadUrls.filter((u) => u !== urlInfo) });
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
}), [uploadChunk, handleChunkCompletion, setCurrentFile]);
|
|
33
|
+
return useCallback(function onUploading(chunks) {
|
|
34
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
35
|
+
for (const { url, chunk } of chunks) {
|
|
36
|
+
yield putChunk(url, chunk);
|
|
37
|
+
}
|
|
38
|
+
setCurrentFile((prev) => {
|
|
39
|
+
if (!prev)
|
|
40
|
+
return prev;
|
|
41
|
+
setUploadStore({
|
|
42
|
+
type: 'edit_file',
|
|
43
|
+
identifier,
|
|
44
|
+
file: Object.assign(Object.assign({}, prev), { fileStatus: FILE_UPLOAD_STATUS.ALL_UPLOADED }),
|
|
45
|
+
});
|
|
46
|
+
return null;
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
}, [identifier, putChunk, setCurrentFile, setUploadStore]);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export { useCurrentFileOnUploading };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { useAtomValue, useSetAtom } from 'jotai';
|
|
2
|
+
import { useContext, useEffect } from 'react';
|
|
3
|
+
import { FILE_UPLOAD_STATUS } from '../types.js';
|
|
4
|
+
import { UploadStoreContext } from '../UploadStoreProvider/UploadStoreProvider.js';
|
|
5
|
+
import { currentFileAtom } from './useCurrentFile.js';
|
|
6
|
+
import { IdentifierContext } from '../FileUploaderImpl/FileUploaderContextProvider.js';
|
|
7
|
+
import { formatUnfinishedUploads } from '../UploadStoreProvider/useSaveUnfinishedUploads.js';
|
|
8
|
+
|
|
9
|
+
function useCurrentFileSetupAndBackUp() {
|
|
10
|
+
const identifier = useContext(IdentifierContext);
|
|
11
|
+
const uploadStore = useContext(UploadStoreContext);
|
|
12
|
+
const currentFile = useAtomValue(currentFileAtom);
|
|
13
|
+
const setCurrentFile = useSetAtom(currentFileAtom);
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
const fileList = uploadStore[identifier];
|
|
16
|
+
if (!fileList || fileList.length === 0) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const uploadingFile = fileList.find((file) => file.fileStatus === FILE_UPLOAD_STATUS.UPLOADING);
|
|
20
|
+
if (uploadingFile) {
|
|
21
|
+
setCurrentFile(Object.assign(Object.assign({}, uploadingFile), { fileStatus: FILE_UPLOAD_STATUS.INIT }));
|
|
22
|
+
}
|
|
23
|
+
}, [identifier, setCurrentFile, uploadStore]);
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
window.addEventListener('beforeunload', saveUnfinishedUpload);
|
|
26
|
+
return () => {
|
|
27
|
+
window.removeEventListener('beforeunload', saveUnfinishedUpload);
|
|
28
|
+
};
|
|
29
|
+
function saveUnfinishedUpload() {
|
|
30
|
+
if (!currentFile)
|
|
31
|
+
return;
|
|
32
|
+
if (currentFile.fileStatus === FILE_UPLOAD_STATUS.UPLOADING) {
|
|
33
|
+
localStorage.setItem(identifier + '_uploading', formatUnfinishedUploads([currentFile]));
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}, [currentFile, identifier]);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export { useCurrentFileSetupAndBackUp };
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { __awaiter } from 'tslib';
|
|
2
|
+
import { App } from 'antd';
|
|
3
|
+
import { useContext, useState } from 'react';
|
|
4
|
+
import '../utils/checkExpiryTime.js';
|
|
5
|
+
import { createFileToUpload } from '../utils/createFileToUpload.js';
|
|
6
|
+
import { addFilesToIndexdb } from '../utils/fileDB/addFilesToIndexdb.js';
|
|
7
|
+
import { useFindDuplicates } from './useFormatFilesFindDuplicates.js';
|
|
8
|
+
import { useRemoveDuplicates } from './useFormatFilesRemoveDuplicates.js';
|
|
9
|
+
import { AllUploaderManagersContext, UploadStoreDispatchContext } from '../UploadStoreProvider/UploadStoreProvider.js';
|
|
10
|
+
import { FILE_UPLOAD_STATUS } from '../types.js';
|
|
11
|
+
import { useTranslate } from '../Locale/useTranslate.js';
|
|
12
|
+
import { RootContext, IdentifierContext, ChunkSizeContext } from '../FileUploaderImpl/FileUploaderContextProvider.js';
|
|
13
|
+
|
|
14
|
+
function useFormatFiles() {
|
|
15
|
+
const t = useTranslate();
|
|
16
|
+
const { message } = App.useApp();
|
|
17
|
+
const root = useContext(RootContext);
|
|
18
|
+
const identifier = useContext(IdentifierContext);
|
|
19
|
+
const chunkSize = useContext(ChunkSizeContext);
|
|
20
|
+
const allUploaderManagers = useContext(AllUploaderManagersContext);
|
|
21
|
+
const setUploadStore = useContext(UploadStoreDispatchContext);
|
|
22
|
+
const { getUploadUrls, onBeforeUpload } = allUploaderManagers[identifier];
|
|
23
|
+
const [isFormatingFiles, setIsFormatingFiles] = useState(false);
|
|
24
|
+
const findDuplicates = useFindDuplicates();
|
|
25
|
+
const removeDuplicatesInUploadQueue = useRemoveDuplicates();
|
|
26
|
+
return { isFormatingFiles, formatFiles };
|
|
27
|
+
function formatFiles(allFiles) {
|
|
28
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
29
|
+
setIsFormatingFiles(true);
|
|
30
|
+
const filesToUpload = yield handleDuplicatesFiles(allFiles);
|
|
31
|
+
const uploadableFiles = yield createUploadableFiles(filesToUpload);
|
|
32
|
+
setUploadStore({ type: 'add_files', identifier, files: uploadableFiles });
|
|
33
|
+
addFilesToIndexdb(identifier, uploadableFiles.map((f) => f.raw));
|
|
34
|
+
setIsFormatingFiles(false);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
function handleDuplicatesFiles(files) {
|
|
38
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
39
|
+
const [shouldOverwrite, duplicateFileNames] = yield findDuplicates(files);
|
|
40
|
+
if (shouldOverwrite) {
|
|
41
|
+
removeDuplicatesInUploadQueue(duplicateFileNames);
|
|
42
|
+
return files;
|
|
43
|
+
}
|
|
44
|
+
return files.filter((f) => !duplicateFileNames.has(f.name));
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
function createUploadableFiles(files) {
|
|
48
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
49
|
+
const promises = files.map((file) => createFileToUpload(file, root, getUploadUrls, onBeforeUpload, chunkSize));
|
|
50
|
+
/* 过滤器是为了通过类型检查而设置的,如果按要求传递 getUploadUrls,状态应该总是 fulfilled */
|
|
51
|
+
const result = (yield Promise.allSettled(promises))
|
|
52
|
+
.filter((r) => r.status === 'fulfilled')
|
|
53
|
+
.map((f) => f.value);
|
|
54
|
+
if (result.some((f) => f.fileStatus === FILE_UPLOAD_STATUS.FAILED) ||
|
|
55
|
+
/** 因上述原因,这个条件应该总是为 false, 但为了保险,还是保留 */
|
|
56
|
+
result.length < files.length) {
|
|
57
|
+
message.info(t('部分文件获取上传地址失败'));
|
|
58
|
+
}
|
|
59
|
+
return result;
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export { useFormatFiles };
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { __awaiter } from 'tslib';
|
|
2
|
+
import { App } from 'antd';
|
|
3
|
+
import { useContext } from 'react';
|
|
4
|
+
import { UploadStoreContext } from '../UploadStoreProvider/UploadStoreProvider.js';
|
|
5
|
+
import { confirmModalConfig } from '../utils/modalConfig.js';
|
|
6
|
+
import { useTranslate } from '../Locale/useTranslate.js';
|
|
7
|
+
import { RootContext, IdentifierContext, ExternalUploadContextContext, ExternalUploadContextOnlyContext } from '../FileUploaderImpl/FileUploaderContextProvider.js';
|
|
8
|
+
|
|
9
|
+
function useFindDuplicates() {
|
|
10
|
+
const { modal } = App.useApp();
|
|
11
|
+
const t = useTranslate();
|
|
12
|
+
const root = useContext(RootContext);
|
|
13
|
+
const identifier = useContext(IdentifierContext);
|
|
14
|
+
const uploadStore = useContext(UploadStoreContext);
|
|
15
|
+
const externalUploadContext = useContext(ExternalUploadContextContext);
|
|
16
|
+
const externalUploadContextOnly = useContext(ExternalUploadContextOnlyContext);
|
|
17
|
+
/**
|
|
18
|
+
* 检查重复文件并询问用户是否覆盖
|
|
19
|
+
* @returns [是否覆盖, 重复文件名列表]
|
|
20
|
+
*/
|
|
21
|
+
return function findDuplicates(files) {
|
|
22
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
23
|
+
const duplicateFiles = externalUploadContextOnly
|
|
24
|
+
? checkForDuplicatesInExternalUploadContext(files, externalUploadContext !== null && externalUploadContext !== void 0 ? externalUploadContext : [])
|
|
25
|
+
: [
|
|
26
|
+
...checkForDuplicatesInUploads(files, uploadStore[identifier], root),
|
|
27
|
+
...checkForDuplicatesInExternalUploadContext(files, externalUploadContext !== null && externalUploadContext !== void 0 ? externalUploadContext : []),
|
|
28
|
+
];
|
|
29
|
+
if (duplicateFiles.length) {
|
|
30
|
+
const userChoice = yield modal.confirm(Object.assign(Object.assign({}, confirmModalConfig), { okText: t('覆盖'), cancelText: t('取消'), title: t('发现同名文件,是否覆盖?') }));
|
|
31
|
+
return [userChoice, new Set(duplicateFiles)];
|
|
32
|
+
}
|
|
33
|
+
return [true, new Set()];
|
|
34
|
+
});
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
function checkForDuplicatesInUploads(files, uploads, root) {
|
|
38
|
+
// 获取已存在的文件名集合
|
|
39
|
+
const existingFiles = new Set(uploads.map((f) => f.fileName));
|
|
40
|
+
// 检查新上传的文件是否与现有文件重名
|
|
41
|
+
const duplicateFiles = files
|
|
42
|
+
.filter((file) => {
|
|
43
|
+
const fileName = root ? `${root}${file.name}` : file.name;
|
|
44
|
+
return existingFiles.has(fileName);
|
|
45
|
+
})
|
|
46
|
+
.map((file) => file.name); // 最后,我们只保留重复文件的名称
|
|
47
|
+
return duplicateFiles;
|
|
48
|
+
}
|
|
49
|
+
function checkForDuplicatesInExternalUploadContext(files, externalUploadContext) {
|
|
50
|
+
// 检查新上传的文件是否与现有文件重名
|
|
51
|
+
const duplicateFiles = files
|
|
52
|
+
.filter((file) => {
|
|
53
|
+
var _a;
|
|
54
|
+
// 判断当前文件是否为文件夹
|
|
55
|
+
// 如果文件名中包含 '/', 则认为它是一个文件夹
|
|
56
|
+
const isNewFileFolder = file.name.includes('/');
|
|
57
|
+
// 获取文件或文件夹的第一级名称
|
|
58
|
+
// 例如,对于 "folder/file.txt",只取 "folder"
|
|
59
|
+
const topLevelName = file.name.split('/')[0];
|
|
60
|
+
// 检查这个名称在已存在的文件列表中是否为文件夹
|
|
61
|
+
// existingFiles 是一个 Map,键是文件名,值是布尔值(true 表示文件夹,false 表示文件)
|
|
62
|
+
const isExistingFileFolder = (_a = externalUploadContext.find((v) => v.fileName === topLevelName)) === null || _a === void 0 ? void 0 : _a.isFolder;
|
|
63
|
+
// 比较新文件和已存在文件的类型(文件夹或非文件夹)是否相同
|
|
64
|
+
if (isNewFileFolder === isExistingFileFolder) {
|
|
65
|
+
// 如果类型相同(都是文件夹或都不是文件夹),则认为是重复的
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
// 如果类型不同,则不是重复的
|
|
69
|
+
return false;
|
|
70
|
+
})
|
|
71
|
+
.map((file) => file.name); // 最后,只保留重复文件的名称
|
|
72
|
+
return duplicateFiles;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export { useFindDuplicates };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { useContext } from 'react';
|
|
2
|
+
import { UploadStoreContext } from '../UploadStoreProvider/UploadStoreProvider.js';
|
|
3
|
+
import { useCancelUpload } from './useCancelUpload.js';
|
|
4
|
+
import { IdentifierContext } from '../FileUploaderImpl/FileUploaderContextProvider.js';
|
|
5
|
+
|
|
6
|
+
function useRemoveDuplicates() {
|
|
7
|
+
const identifier = useContext(IdentifierContext);
|
|
8
|
+
const uploadStore = useContext(UploadStoreContext);
|
|
9
|
+
const cancelUpload = useCancelUpload();
|
|
10
|
+
return function removeDuplicates(duplicationOfName) {
|
|
11
|
+
const fileList = uploadStore[identifier];
|
|
12
|
+
for (const fileName of duplicationOfName) {
|
|
13
|
+
const upload = fileList.find((f) => f.fileName === fileName);
|
|
14
|
+
if (upload) {
|
|
15
|
+
cancelUpload(upload);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export { useRemoveDuplicates };
|