import type { ComponentProcessProps } from "components/system/Apps/RenderComponent"; import StyledButton from "components/system/Dialogs/Transfer/StyledButton"; import StyledTransfer from "components/system/Dialogs/Transfer/StyledTransfer"; import type { FileReaders, ObjectReaders, } from "components/system/Dialogs/Transfer/useTransferDialog"; import { useProcesses } from "contexts/process"; import { basename, dirname } from "path"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { ONE_TIME_PASSIVE_EVENT } from "utils/constants"; import { haltEvent } from "utils/functions"; const MAX_TITLE_LENGTH = 37; const isFileReaders = ( readers?: FileReaders | ObjectReaders ): readers is FileReaders => Array.isArray(readers?.[0]); const Transfer: FC = ({ id }) => { const { argument, closeWithTransition, processes: { [id]: process } = {}, title, } = useProcesses(); const { closing, fileReaders, url } = process || {}; const [currentTransfer, setCurrentTransfer] = useState<[string, File]>(); const [cd = "", { name = "" } = {}] = currentTransfer || []; const [progress, setProgress] = useState(0); const actionName = useMemo( () => (url && !fileReaders ? "Extraindo" : "Copiando"), [fileReaders, url] ); const processing = useRef(false); const completeTransfer = useCallback(() => { processing.current = false; closeWithTransition(id); }, [closeWithTransition, id]); const processObjectReader = useCallback( ([reader, ...remainingReaders]: ObjectReaders) => { const isComplete = remainingReaders.length === 0; reader.read().then(() => { setProgress((currentProgress) => currentProgress + 1); if (isComplete) { reader.done?.(); completeTransfer(); } else { const [{ directory, name: nextName }] = remainingReaders; setCurrentTransfer([directory, { name: nextName } as File]); } }); if (!isComplete) processObjectReader(remainingReaders); }, [completeTransfer] ); const processFileReader = useCallback( ([[file, directory, reader], ...remainingReaders]: FileReaders) => { let fileProgress = 0; setCurrentTransfer([directory, file]); reader.addEventListener( "progress", ({ loaded = 0 }) => { const progressLoaded = loaded - fileProgress; setProgress((currentProgress) => currentProgress + progressLoaded); fileProgress = loaded; }, { passive: true } ); reader.addEventListener( "loadend", () => { if (remainingReaders.length > 0) { processFileReader(remainingReaders); } else { completeTransfer(); } }, ONE_TIME_PASSIVE_EVENT ); reader.readAsArrayBuffer(file); }, [completeTransfer] ); const totalTransferSize = useMemo( () => isFileReaders(fileReaders) ? fileReaders.reduce((acc, [{ size = 0 }]) => acc + size, 0) : fileReaders?.length || Number.POSITIVE_INFINITY, [fileReaders] ); useEffect(() => { if (!processing.current) { if (fileReaders) { if (fileReaders?.length > 0) { processing.current = true; if (isFileReaders(fileReaders)) { processFileReader(fileReaders); } else { const [{ directory, name: firstName }] = fileReaders; setCurrentTransfer([directory, { name: firstName } as File]); processObjectReader(fileReaders); } } else { closeWithTransition(id); } } else if (url) { setCurrentTransfer([dirname(url), { name: basename(url) } as File]); } } }, [ closeWithTransition, fileReaders, id, processFileReader, processObjectReader, url, ]); useEffect(() => { if (processing.current) { const progressPercent = Math.floor((progress / totalTransferSize) * 100); argument(id, "progress", progressPercent); title(id, `${progressPercent}% completo`); } }, [argument, id, progress, title, totalTransferSize]); useEffect(() => title(id, `${actionName}...`), [actionName, id, title]); useEffect( () => () => { if (closing && processing.current) { if (isFileReaders(fileReaders)) { // eslint-disable-next-line unicorn/no-unreadable-array-destructuring fileReaders.forEach(([, , reader]) => reader.abort()); } else { fileReaders?.forEach((reader) => reader.abort()); fileReaders?.[0]?.done?.(); } } }, [closing, fileReaders] ); return (

{name ? `${actionName} '${ name.length >= MAX_TITLE_LENGTH ? `${name.slice(0, MAX_TITLE_LENGTH)}...` : name }'` : ""}

{cd ? `Para '${cd}'` : ""}

); }; export default Transfer;