109 lines
2.9 KiB
JavaScript
109 lines
2.9 KiB
JavaScript
import { useState } from 'react';
|
|
import { fetchFormats, uploadFiles } from '../api.js';
|
|
import { extensionOf } from '../utils/archiveExtensions.js';
|
|
|
|
const DEFAULT_QUALITY = {
|
|
jpg: 80,
|
|
jpeg: 80,
|
|
webp: 80,
|
|
avif: 50,
|
|
tiff: 80,
|
|
png: 6,
|
|
zip: 6,
|
|
'tar.gz': 6,
|
|
'tar.bz2': 9,
|
|
'7z': 5,
|
|
'tar.7z': 5,
|
|
mp3: 192,
|
|
ogg: 192,
|
|
aac: 192,
|
|
m4a: 192,
|
|
};
|
|
|
|
const DEFAULT_ICON_SIZE = 256;
|
|
|
|
function defaultQualityFor(targetFormat) {
|
|
return DEFAULT_QUALITY[targetFormat] ?? null;
|
|
}
|
|
|
|
export function useConverterWorkflow({ preferredTargetFormat } = {}) {
|
|
const [pendingFiles, setPendingFiles] = useState([]);
|
|
const [submittedJobs, setSubmittedJobs] = useState([]);
|
|
|
|
async function handleFilesSelected(fileList) {
|
|
const files = Array.from(fileList);
|
|
const withTargets = await Promise.all(
|
|
files.map(async (file) => {
|
|
const targets = await fetchFormats(extensionOf(file.name));
|
|
const targetFormat =
|
|
preferredTargetFormat && targets.includes(preferredTargetFormat)
|
|
? preferredTargetFormat
|
|
: targets[0] ?? null;
|
|
return {
|
|
file,
|
|
targets,
|
|
targetFormat,
|
|
quality: defaultQualityFor(targetFormat),
|
|
iconSize: targetFormat === 'ico' ? DEFAULT_ICON_SIZE : null,
|
|
};
|
|
})
|
|
);
|
|
setPendingFiles((current) => [...current, ...withTargets]);
|
|
}
|
|
|
|
function updateTargetFormat(index, targetFormat) {
|
|
setPendingFiles((current) =>
|
|
current.map((item, i) =>
|
|
i === index
|
|
? {
|
|
...item,
|
|
targetFormat,
|
|
quality: defaultQualityFor(targetFormat),
|
|
iconSize: targetFormat === 'ico' ? DEFAULT_ICON_SIZE : null,
|
|
}
|
|
: item
|
|
)
|
|
);
|
|
}
|
|
|
|
function updateQuality(index, quality) {
|
|
setPendingFiles((current) => current.map((item, i) => (i === index ? { ...item, quality } : item)));
|
|
}
|
|
|
|
function updateIconSize(index, iconSize) {
|
|
setPendingFiles((current) => current.map((item, i) => (i === index ? { ...item, iconSize } : item)));
|
|
}
|
|
|
|
function removePendingFile(index) {
|
|
setPendingFiles((current) => current.filter((_, i) => i !== index));
|
|
}
|
|
|
|
function removeSubmittedJob(index) {
|
|
setSubmittedJobs((current) => current.filter((_, i) => i !== index));
|
|
}
|
|
|
|
async function handleConvert() {
|
|
const validItems = pendingFiles.filter((item) => item.targetFormat);
|
|
const jobs = await uploadFiles(validItems);
|
|
const jobsWithSize = jobs.map((job, i) => ({
|
|
...job,
|
|
size: validItems[i].file.size,
|
|
targetFormat: validItems[i].targetFormat,
|
|
}));
|
|
setSubmittedJobs((current) => [...current, ...jobsWithSize]);
|
|
setPendingFiles([]);
|
|
}
|
|
|
|
return {
|
|
pendingFiles,
|
|
submittedJobs,
|
|
handleFilesSelected,
|
|
updateTargetFormat,
|
|
updateQuality,
|
|
updateIconSize,
|
|
removePendingFile,
|
|
removeSubmittedJob,
|
|
handleConvert,
|
|
};
|
|
}
|