feat(seo): add conversion-page scaffolding with 2 seed pairs (jpg-to-png, pdf-to-docx)
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
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,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user