fix: use upload and download abort signals (#212)

* fix: use upload and download abort signals

* fix: progress trackers

chore: update fm-lib and bee-js

* chore: bump-up fm-lib version
This commit is contained in:
Bálint Ujvári
2026-03-05 16:55:09 +01:00
parent e00918b192
commit 308ec3dcc0
13 changed files with 154 additions and 85 deletions
+2 -2
View File
@@ -53,11 +53,11 @@
"dependencies": {
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.1",
"@ethersphere/bee-js": "^10.4.0",
"@ethersphere/bee-js": "^11.1.1",
"@formbricks/js": "^4.3.0",
"@mui/icons-material": "^7.3.7",
"@mui/material": "^7.3.7",
"@solarpunkltd/file-manager-lib": "^1.0.5",
"@solarpunkltd/file-manager-lib": "^1.0.7",
"axios": "^0.30.2",
"bignumber.js": "^9.3.1",
"dotted-map": "^2.2.3",
+17 -16
View File
@@ -15,8 +15,8 @@ importers:
specifier: ^11.14.1
version: 11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@types/react@19.2.14)(react@19.2.4)
'@ethersphere/bee-js':
specifier: ^10.4.0
version: 10.4.0
specifier: ^11.1.1
version: 11.1.1
'@formbricks/js':
specifier: ^4.3.0
version: 4.3.0
@@ -27,8 +27,8 @@ importers:
specifier: ^7.3.7
version: 7.3.8(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@types/react@19.2.14)(react@19.2.4))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
'@solarpunkltd/file-manager-lib':
specifier: ^1.0.5
version: 1.0.5
specifier: ^1.0.7
version: 1.0.7
axios:
specifier: ^0.30.2
version: 0.30.2(debug@4.4.3)
@@ -1256,8 +1256,8 @@ packages:
resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@ethersphere/bee-js@10.4.0':
resolution: {integrity: sha512-dtnyvKA3prBj22k2mfZWPq+uiK1hLMKr/jrGX4vaS41JsHX9uJ1GMGr4vCc41ANstGUGbp1dwCUWsXkqqjWuvg==}
'@ethersphere/bee-js@11.1.1':
resolution: {integrity: sha512-s2IpuVpy74cJyhj5yugO3+c9eR/r9TZsVJABk2iHWtTVkoA1qZdvgUjzV0w962o1gXrmYdxX4NOmlyIEpY11iQ==}
engines: {bee: 2.4.0-390a402e, beeApiVersion: 7.2.0}
'@formbricks/js@4.3.0':
@@ -1833,9 +1833,9 @@ packages:
'@sinonjs/fake-timers@13.0.5':
resolution: {integrity: sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==}
'@solarpunkltd/file-manager-lib@1.0.5':
resolution: {integrity: sha512-s/2HP/VCrdoWOAZfZ7gl+maxO4D8wR3INdz9XSIjjvwlWU/KBUV3Vke5ANRuy28ikyDT4qOggu4G69EBHrl5YA==}
engines: {bee: 2.6.0, node: '>=20.0.0', npm: '>=11.0.0', pnpm: '>=10.0.0'}
'@solarpunkltd/file-manager-lib@1.0.7':
resolution: {integrity: sha512-L/mE2F/4oL24PHUNcSET2TlvGpuVlm8AFedpBl/2O59ISrBvLzs6H2jep5LytgRdwaD+Hpot2ssGkWKgHnycrQ==}
engines: {bee: 2.7.0, node: '>=24.0.0', npm: '>=11.0.0', pnpm: '>=10.0.0'}
'@testing-library/dom@10.4.1':
resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==}
@@ -2624,8 +2624,8 @@ packages:
resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==}
engines: {node: '>= 0.8'}
cafe-utility@33.6.0:
resolution: {integrity: sha512-MyXjck4cf6+WahnRWpS083qA0Ib9XAgSVOfdd+mSwAWiyK0fMs0+khXHTLHTRA+nIZIJFVDEcMX8Cnc8G8NEDw==}
cafe-utility@33.8.0:
resolution: {integrity: sha512-qfbG8nHTY5jBfCSedG9+b57avhKePdiHfj2w0FMGokJuQU+3dxeT9+qasMReoXHBDp38CFHMSEvz5X0SDCXbWA==}
call-bind-apply-helpers@1.0.2:
resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
@@ -6909,10 +6909,10 @@ snapshots:
'@eslint/core': 0.17.0
levn: 0.4.1
'@ethersphere/bee-js@10.4.0':
'@ethersphere/bee-js@11.1.1':
dependencies:
axios: 0.30.2(debug@4.4.3)
cafe-utility: 33.6.0
cafe-utility: 33.8.0
debug: 4.4.3
isomorphic-ws: 4.0.1(ws@8.19.0)
semver: 7.7.4
@@ -7539,9 +7539,10 @@ snapshots:
dependencies:
'@sinonjs/commons': 3.0.1
'@solarpunkltd/file-manager-lib@1.0.5':
'@solarpunkltd/file-manager-lib@1.0.7':
dependencies:
'@ethersphere/bee-js': 10.4.0
'@ethersphere/bee-js': 11.1.1
cafe-utility: 33.8.0
std-env: 3.10.0
transitivePeerDependencies:
- bufferutil
@@ -8461,7 +8462,7 @@ snapshots:
bytes@3.1.2: {}
cafe-utility@33.6.0: {}
cafe-utility@33.8.0: {}
call-bind-apply-helpers@1.0.2:
dependencies:
@@ -62,6 +62,8 @@ export function CreateDriveModal({
const validationError = duplicate && nameExists ? 'Drive already exists. Please choose another name.' : ''
useEffect(() => {
isMountedRef.current = true
return () => {
isMountedRef.current = false
}
@@ -210,6 +210,7 @@ export function FileBrowser({ errorMessage, setErrorMessage }: FileBrowserProps)
const [confirmBulkRestore, setConfirmBulkRestore] = useState(false)
const [isRefreshing, setIsRefreshing] = useState(false)
const [pendingCancelUpload, setPendingCancelUpload] = useState<string | null>(null)
const [pendingCancelDownload, setPendingCancelDownload] = useState<string | null>(null)
const q = query.trim().toLowerCase()
const isSearchMode = q.length > 0
@@ -371,6 +372,16 @@ export function FileBrowser({ errorMessage, setErrorMessage }: FileBrowserProps)
setShowError,
])
const handleDownloadClose = (uuid: string) => {
const row = downloadItems.find(i => i.uuid === uuid)
if (row?.status === TransferStatus.Downloading) {
setPendingCancelDownload(uuid)
} else {
cancelOrDismissDownload(uuid)
}
}
const handleUploadClose = (uuid: string) => {
const row = uploadItems.find(i => i.uuid === uuid)
@@ -425,6 +436,18 @@ export function FileBrowser({ errorMessage, setErrorMessage }: FileBrowserProps)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [showContext, pos, contextRef])
useEffect(() => {
isMountedRef.current = true
return () => {
isMountedRef.current = false
if (rafIdRef.current) {
cancelAnimationFrame(rafIdRef.current)
}
}
}, [])
useEffect(() => {
let title = currentDrive?.name || ''
@@ -446,16 +469,6 @@ export function FileBrowser({ errorMessage, setErrorMessage }: FileBrowserProps)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isSearchMode])
useEffect(() => {
return () => {
isMountedRef.current = false
if (rafIdRef.current) {
cancelAnimationFrame(rafIdRef.current)
}
}
}, [])
const doRefresh = async () => {
handleCloseContext()
@@ -610,6 +623,14 @@ export function FileBrowser({ errorMessage, setErrorMessage }: FileBrowserProps)
}
}}
onCancelUploadCancel={() => setPendingCancelUpload(null)}
pendingCancelDownload={pendingCancelDownload}
onCancelDownloadConfirm={() => {
if (pendingCancelDownload) {
cancelOrDismissDownload(pendingCancelDownload)
setPendingCancelDownload(null)
}
}}
onCancelDownloadCancel={() => setPendingCancelDownload(null)}
/>
{isRefreshing && (
@@ -644,7 +665,7 @@ export function FileBrowser({ errorMessage, setErrorMessage }: FileBrowserProps)
type={FileTransferType.Download}
open={isDownloading}
items={downloadItems}
onRowClose={(name: string) => cancelOrDismissDownload(name)}
onRowClose={handleDownloadClose}
onCloseAll={() => dismissAllDownloads()}
/>
<NotificationBar setErrorMessage={setErrorMessage} />
@@ -17,6 +17,7 @@ interface FileBrowserModalsProps {
confirmBulkRestore: boolean
showDestroyDriveModal: boolean
pendingCancelUpload: string | null
pendingCancelDownload: string | null
onDeleteCancel: () => void
onDeleteProceed: (action: FileAction) => void
onForgetConfirm: () => Promise<void>
@@ -27,6 +28,8 @@ interface FileBrowserModalsProps {
onDestroyConfirm: () => Promise<void>
onCancelUploadConfirm: () => void
onCancelUploadCancel: () => void
onCancelDownloadConfirm: () => void
onCancelDownloadCancel: () => void
}
export function FileBrowserModals({
@@ -38,6 +41,7 @@ export function FileBrowserModals({
confirmBulkRestore,
showDestroyDriveModal,
pendingCancelUpload,
pendingCancelDownload,
onDeleteCancel,
onDeleteProceed,
onForgetConfirm,
@@ -48,6 +52,8 @@ export function FileBrowserModals({
onDestroyConfirm,
onCancelUploadConfirm,
onCancelUploadCancel,
onCancelDownloadCancel,
onCancelDownloadConfirm,
}: FileBrowserModalsProps): ReactElement {
return (
<>
@@ -124,6 +130,17 @@ export function FileBrowserModals({
onCancel={onCancelUploadCancel}
/>
)}
{pendingCancelDownload && (
<ConfirmModal
title="Cancel download?"
message="Are you sure you want to cancel this download?"
confirmLabel="Cancel download"
cancelLabel="Keep downloading"
onConfirm={onCancelDownloadConfirm}
onCancel={onCancelDownloadCancel}
/>
)}
</>
)
}
@@ -20,7 +20,7 @@ import { DownloadProgress, FileAction, TrackDownloadProps, ViewType } from '../.
import { useContextMenu } from '../../../hooks/useContextMenu'
import { getUsableStamps, handleDestroyAndForgetDrive, verifyDriveSpace } from '../../../utils/bee'
import { Dir, formatBytes, isTrashed, safeSetState, truncateNameMiddle } from '../../../utils/common'
import { createDownloadAbort, startDownloadingQueue } from '../../../utils/download'
import { startDownloadingQueue } from '../../../utils/download'
import { FileOperation, performFileOperation } from '../../../utils/fileOperations'
import { GetIconElement } from '../../../utils/GetIconElement'
import type { FilePropertyGroup } from '../../../utils/infoGroups'
@@ -168,15 +168,14 @@ export function FileItem({
const rawSize = latestFileInfo.customMetadata?.size
const expectedSize = rawSize ? Number(rawSize) : undefined
createDownloadAbort(latestFileInfo.name)
const uuid = uuidV4()
await startDownloadingQueue(
fm,
[latestFileInfo],
[{ uuid, info: latestFileInfo }],
[
onDownload({
uuid: uuidV4(),
uuid,
name: latestFileInfo.name,
size: formatBytes(rawSize),
expectedSize,
@@ -89,6 +89,8 @@ export function InitialModal({
const isMountedRef = useRef(true)
useEffect(() => {
isMountedRef.current = true
return () => {
isMountedRef.current = false
}
@@ -159,6 +159,14 @@ export function UpgradeDriveModal({
[beeApi, walletBalance, isMountedRef, setErrorMessage, setShowError],
)
useEffect(() => {
isMountedRef.current = true
return () => {
isMountedRef.current = false
}
}, [])
useEffect(() => {
const fetchSizes = () => {
const sizes = Array.from(Utils.getStampEffectiveBytesBreakpoints(false, defaultErasureCodeLevel).values())
@@ -207,12 +215,6 @@ export function UpgradeDriveModal({
setValidityEndDate(getExpiryDateByLifetime(lifetimeIndex, stamp.duration.toEndDate()))
}, [lifetimeIndex, stamp.duration])
useEffect(() => {
return () => {
isMountedRef.current = false
}
}, [])
const batchIdStr = stamp.batchID.toString()
const shortBatchId = batchIdStr.length > 12 ? `${batchIdStr.slice(0, 4)}...${batchIdStr.slice(-4)}` : batchIdStr
@@ -426,13 +426,16 @@ export function VersionsList({ versions, headFi, restoreVersion, onDownload }: V
handleCloseContext()
if (!fm || !beeApi) return
const rawSize = fileInfo.customMetadata?.size
const expectedSize = rawSize ? Number(rawSize) : undefined
const driveName = drives.find(d => d.id.toString() === fileInfo.driveId.toString())?.name ?? currentDrive?.name
const uuid = uuidV4()
await startDownloadingQueue(
fm,
[fileInfo],
[onDownload({ uuid: uuidV4(), name: fileInfo.name, size: formatBytes(rawSize), expectedSize, driveName })],
[{ uuid, info: fileInfo }],
[onDownload({ uuid, name: fileInfo.name, size: formatBytes(rawSize), expectedSize, driveName })],
)
},
[handleCloseContext, fm, beeApi, onDownload, drives, currentDrive],
@@ -8,7 +8,7 @@ import { uuidV4 } from '../../../utils'
import { DownloadProgress, TrackDownloadProps } from '../constants/transfers'
import { getUsableStamps } from '../utils/bee'
import { formatBytes, getFileId, safeSetState } from '../utils/common'
import { startDownloadingQueue } from '../utils/download'
import { FileInfoWithUUID, startDownloadingQueue } from '../utils/download'
import { FileOperation, performBulkFileOperation } from '../utils/fileOperations'
interface BulkOptions {
@@ -77,23 +77,28 @@ export function useBulkActions({ listToRender, setErrorMessage, trackDownload }:
async (list: FileInfo[]) => {
if (!fm || !list?.length) return
const trackers: Array<(progress: DownloadProgress) => void> = []
for (const fi of list) {
const trackers = new Array<(progress: DownloadProgress) => void>(list.length)
const infoListWitIDs: FileInfoWithUUID[] = new Array<FileInfoWithUUID>(list.length)
for (let i = 0; i < list.length; i++) {
const fi = list[i]
const rawSize = fi.customMetadata?.size as string | number | undefined
const prettySize = formatBytes(rawSize)
const expected = rawSize ? Number(rawSize) : undefined
const driveName = drives.find(d => d.id.toString() === fi.driveId.toString())?.name
const tracker = trackDownload({
uuid: uuidV4(),
const uuid = uuidV4()
infoListWitIDs[i] = { uuid, info: fi }
trackers[i] = trackDownload({
uuid,
name: fi.name,
size: prettySize,
expectedSize: expected,
driveName,
})
trackers.push(tracker)
}
await startDownloadingQueue(fm, list, trackers)
await startDownloadingQueue(fm, infoListWitIDs, trackers)
},
[fm, trackDownload, drives],
)
+10 -1
View File
@@ -172,6 +172,7 @@ export function useTransfers({ setErrorMessage }: TransferProps) {
const { fm, adminDrive, currentDrive, currentStamp, files, setShowError, refreshStamp } = useContext(FMContext)
const { beeApi } = useContext(SettingsContext)
const [openConflict, conflictPortal] = useUploadConflictDialog()
const isMountedRef = useRef(true)
const uploadAbortsRef = useRef<AbortManager>(new AbortManager())
const queueRef = useRef<UploadTask[]>([])
@@ -406,6 +407,7 @@ export function useTransfers({ setErrorMessage }: TransferProps) {
taskDrive,
{ ...info, onUploadProgress: progressCb },
{ actHistoryAddress: task.isReplace ? task.replaceHistory : undefined },
{ signal },
)
await Promise.race([uploadPromise, checkCancellation])
@@ -827,6 +829,14 @@ export function useTransfers({ setErrorMessage }: TransferProps) {
cancelledDownloadingRef.current.clear()
}, [])
useEffect(() => {
isMountedRef.current = true
return () => {
isMountedRef.current = false
}
}, [])
useEffect(() => {
const handleFileUploaded = (e: Event) => {
const { fileInfo } = (e as CustomEvent).detail || {}
@@ -853,7 +863,6 @@ export function useTransfers({ setErrorMessage }: TransferProps) {
return () => {
window.removeEventListener(FILE_MANAGER_EVENTS.FILE_UPLOADED, handleFileUploaded as EventListener)
isMountedRef.current = false
}
}, [])
+42 -35
View File
@@ -13,12 +13,12 @@ enum Errors {
SecurityError = 'SecurityError',
}
export function createDownloadAbort(name: string): void {
downloadAborts.create(name)
export function createDownloadAbort(id: string): void {
downloadAborts.create(id)
}
export function abortDownload(name: string): void {
downloadAborts.abort(name)
export function abortDownload(id: string): void {
downloadAborts.abort(id)
}
const processStream = async (
@@ -130,8 +130,13 @@ const streamToBlob = async (
return new Blob([combined], { type: mimeType })
}
interface FileInfoWithHandle {
export interface FileInfoWithUUID {
uuid: string
info: FileInfo
}
interface FileInfoWithHandle {
infoWithId: FileInfoWithUUID
handle?: FileSystemFileHandle
cancelled?: boolean
}
@@ -149,17 +154,17 @@ const isUserCancellation = (error: unknown): boolean => {
}
const getSingleFileHandle = async (
info: FileInfo,
infoWithId: FileInfoWithUUID,
defaultDownloadFolder: string,
): Promise<FileInfoWithHandle[] | undefined> => {
const { mime, ext } = guessMime(info.name, info.customMetadata)
const { mime, ext } = guessMime(infoWithId.info.name, infoWithId.info.customMetadata)
const pickerOptions: {
suggestedName: string
startIn: string
types?: Array<{ accept: Record<string, string[]> }>
} = {
suggestedName: info.name,
suggestedName: infoWithId.info.name,
startIn: defaultDownloadFolder,
}
@@ -171,20 +176,20 @@ const getSingleFileHandle = async (
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const handle = (await (window as any).showSaveFilePicker(pickerOptions)) as FileSystemFileHandle
return [{ info, handle }]
return [{ infoWithId, handle }]
} catch (error: unknown) {
return isUserCancellation(error) ? [{ info, cancelled: true }] : undefined
return isUserCancellation(error) ? [{ infoWithId, cancelled: true }] : undefined
}
}
const getMultipleFileHandles = async (
infoList: FileInfo[],
infoWithIdList: FileInfoWithUUID[],
defaultDownloadFolder: string,
): Promise<FileInfoWithHandle[] | undefined> => {
if (!isDirectoryPickerSupported()) {
const handles: FileInfoWithHandle[] = []
for (const info of infoList) {
for (const info of infoWithIdList) {
const result = await getSingleFileHandle(info, defaultDownloadFolder)
if (!result) return undefined
@@ -203,37 +208,37 @@ const getMultipleFileHandles = async (
const handles: FileInfoWithHandle[] = []
for (const info of infoList) {
for (const infoWithId of infoWithIdList) {
try {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const fileHandle = (await (dirHandle as any).getFileHandle(info.name, {
const fileHandle = (await (dirHandle as any).getFileHandle(infoWithId.info.name, {
create: true,
})) as FileSystemFileHandle
handles.push({ info, handle: fileHandle })
handles.push({ infoWithId, handle: fileHandle })
} catch (error: unknown) {
// eslint-disable-next-line no-console
console.error(`Failed to create file handle for ${info.name}:`, error)
handles.push({ info, cancelled: true })
console.error(`Failed to create file handle for ${infoWithId.info.name}:`, error)
handles.push({ infoWithId, cancelled: true })
}
}
return handles
} catch (error: unknown) {
return isUserCancellation(error) ? infoList.map(info => ({ info, cancelled: true })) : undefined
return isUserCancellation(error) ? infoWithIdList.map(infoWithId => ({ infoWithId, cancelled: true })) : undefined
}
}
const getFileHandles = (infoList: FileInfo[]): Promise<FileInfoWithHandle[] | undefined> => {
const getFileHandles = (infoWithIdList: FileInfoWithUUID[]): Promise<FileInfoWithHandle[] | undefined> => {
const defaultDownloadFolder = 'downloads'
if (!isPickerSupported()) return Promise.resolve(infoList.map(info => ({ info })))
if (!isPickerSupported()) return Promise.resolve(infoWithIdList.map(infoWithId => ({ infoWithId })))
if (infoList.length === 1) {
return getSingleFileHandle(infoList[0], defaultDownloadFolder)
if (infoWithIdList.length === 1) {
return getSingleFileHandle(infoWithIdList[0], defaultDownloadFolder)
}
return getMultipleFileHandles(infoList, defaultDownloadFolder)
return getMultipleFileHandles(infoWithIdList, defaultDownloadFolder)
}
const downloadToDisk = async (
@@ -324,26 +329,26 @@ const downloadFromUrl = (url: string, fileName: string): void => {
export const startDownloadingQueue = async (
fm: FileManager,
infoList: FileInfo[],
infoListWithIds: FileInfoWithUUID[],
trackers?: Array<(progress: DownloadProgress) => void>,
isOpenWindow?: boolean,
): Promise<void> => {
if (!infoList.length || (trackers && trackers.length !== infoList.length)) return
if (!infoListWithIds.length || (trackers && trackers.length !== infoListWithIds.length)) return
try {
const fileHandles: FileInfoWithHandle[] | undefined = isOpenWindow
? infoList.map(info => ({ info }))
: await getFileHandles(infoList)
? infoListWithIds.map(infoWithId => ({ infoWithId }))
: await getFileHandles(infoListWithIds)
if (!fileHandles) return
await Promise.all(
fileHandles.map(async (fh, i) => {
const name = fh.info.name
const tracker = trackers ? trackers[i] : undefined
createDownloadAbort(name)
const signal = downloadAborts.getSignal(name)
const uuid = fh.infoWithId.uuid
createDownloadAbort(uuid)
const signal = downloadAborts.getSignal(uuid)
try {
if (fh.cancelled) {
@@ -352,11 +357,13 @@ export const startDownloadingQueue = async (
return
}
const dataStreams = (await fm.download(fh.info)) as ReadableStream<Uint8Array>[]
const dataStreams = (await fm.download(fh.infoWithId.info, undefined, undefined, {
signal,
})) as ReadableStream<Uint8Array>[]
if (!dataStreams || dataStreams.length === 0) {
// eslint-disable-next-line no-console
console.error(`No data streams returned for ${name}`)
console.error(`No data streams returned for ${fh.infoWithId.info.name}`)
tracker?.({ progress: 0, isDownloading: false, state: DownloadState.Error })
return
@@ -365,7 +372,7 @@ export const startDownloadingQueue = async (
let success = false
if (isOpenWindow || !fh.handle) {
success = await downloadToBlob(dataStreams, fh.info, tracker, isOpenWindow, signal)
success = await downloadToBlob(dataStreams, fh.infoWithId.info, tracker, isOpenWindow, signal)
} else {
success = await downloadToDisk(dataStreams, fh.handle, tracker, signal)
}
@@ -375,7 +382,7 @@ export const startDownloadingQueue = async (
}
if (success) {
const size = fh.info.customMetadata?.size
const size = fh.infoWithId.info.customMetadata?.size
const finalProgress = size ? Number(size) : 0
tracker({ progress: finalProgress, isDownloading: false })
@@ -397,7 +404,7 @@ export const startDownloadingQueue = async (
tracker?.({ progress: 0, isDownloading: false, state: DownloadState.Cancelled })
}
} finally {
downloadAborts.abort(name)
downloadAborts.abort(uuid)
}
}),
)
+1
View File
@@ -74,6 +74,7 @@ export default defineConfig(({ mode }) => {
extensions: ['.ts', '.tsx', '.js', '.jsx', '.css', '.scss'],
},
optimizeDeps: {
// include: [],
// exclude: [], // add libs for local development, if needed, e.g.: @solarpunkltd/file-manager-lib
},
build: {