partial synch with ph2 updates
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
import { useState, useCallback } from "react";
|
||||
|
||||
export function useDownloadQueue(maxConcurrent = 3) {
|
||||
const [queue, setQueue] = useState([]); // queued tasks
|
||||
const [activeCount, setActiveCount] = useState(0);
|
||||
const [statuses, setStatuses] = useState({}); // { id: "idle"|"queued"|"downloading"|"done"|"failed" }
|
||||
|
||||
const scheduleNext = useCallback(() => {
|
||||
setQueue((queueCurr) => {
|
||||
if (activeCount >= maxConcurrent || queueCurr.length === 0)
|
||||
return queueCurr;
|
||||
|
||||
const [task, ...rest] = queueCurr;
|
||||
|
||||
setStatuses((s) => ({ ...s, [task.id]: "downloading" }));
|
||||
setActiveCount((c) => c + 1);
|
||||
|
||||
// Run the download fully in async IIFE
|
||||
(async () => {
|
||||
try {
|
||||
await task.downloadFn(); // triggers fetch + blob + <a> click
|
||||
setStatuses((s) => ({ ...s, [task.id]: "done" }));
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
setStatuses((s) => ({ ...s, [task.id]: "failed" }));
|
||||
} finally {
|
||||
setActiveCount((c) => c - 1);
|
||||
scheduleNext(); // promote next in queue
|
||||
}
|
||||
})();
|
||||
|
||||
return rest;
|
||||
});
|
||||
}, [activeCount, maxConcurrent]);
|
||||
|
||||
const startDownload = useCallback(
|
||||
(id, downloadFn) => {
|
||||
setStatuses((s) => ({ ...s, [id]: "queued" }));
|
||||
setQueue((curr) => [...curr, { id, downloadFn }]);
|
||||
scheduleNext();
|
||||
},
|
||||
[scheduleNext]
|
||||
);
|
||||
|
||||
const getStatus = useCallback((id) => statuses[id] || "idle", [statuses]);
|
||||
|
||||
return { startDownload, getStatus };
|
||||
}
|
||||
Reference in New Issue
Block a user