Qortal-Hub/src/common/useFetchResources.tsx
2025-05-09 21:20:38 +02:00

168 lines
5.0 KiB
TypeScript

import { useCallback } from 'react';
import { resourceDownloadControllerAtom } from '../atoms/global';
import { getBaseApiReact } from '../App';
import { useSetAtom } from 'jotai';
export const useFetchResources = () => {
const setResources = useSetAtom(resourceDownloadControllerAtom);
const downloadResource = useCallback(
({ service, name, identifier }, build) => {
setResources((prev) => ({
...prev,
[`${service}-${name}-${identifier}`]: {
...(prev[`${service}-${name}-${identifier}`] || {}),
service,
name,
identifier,
},
}));
try {
let isCalling = false;
let percentLoaded = 0;
let timer = 24;
let tries = 0;
let calledFirstTime = false;
let intervalId;
let timeoutId;
const callFunction = async () => {
if (isCalling) return;
isCalling = true;
let res;
if (!build) {
const urlFirstTime = `${getBaseApiReact()}/arbitrary/resource/status/${service}/${name}/${identifier}`;
const resCall = await fetch(urlFirstTime, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
});
res = await resCall.json();
if (tries > 18) {
if (intervalId) {
clearInterval(intervalId);
}
if (timeoutId) {
clearTimeout(timeoutId);
}
setResources((prev) => ({
...prev,
[`${service}-${name}-${identifier}`]: {
...(prev[`${service}-${name}-${identifier}`] || {}),
status: {
...res,
status: 'FAILED_TO_DOWNLOAD',
},
},
}));
return;
}
tries = tries + 1;
}
if (build || (calledFirstTime === false && res?.status !== 'READY')) {
const url = `${getBaseApiReact()}/arbitrary/resource/properties/${service}/${name}/${identifier}?build=true`;
const resCall = await fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
});
res = await resCall.json();
}
calledFirstTime = true;
isCalling = false;
if (res.localChunkCount) {
if (res.percentLoaded) {
if (
res.percentLoaded === percentLoaded &&
res.percentLoaded !== 100
) {
timer = timer - 5;
} else {
timer = 24;
}
if (timer < 0) {
timer = 24;
isCalling = true;
// Update Recoil state for refetching
setResources((prev) => ({
...prev,
[`${service}-${name}-${identifier}`]: {
...(prev[`${service}-${name}-${identifier}`] || {}),
status: {
...res,
status: 'REFETCHING',
},
},
}));
timeoutId = setTimeout(() => {
isCalling = false;
downloadResource({ name, service, identifier }, true);
}, 25000);
return;
}
percentLoaded = res.percentLoaded;
}
// Update Recoil state for progress
setResources((prev) => ({
...prev,
[`${service}-${name}-${identifier}`]: {
...(prev[`${service}-${name}-${identifier}`] || {}),
status: res,
},
}));
}
// Check if progress is 100% and clear interval if true
if (res?.status === 'READY') {
if (intervalId) {
clearInterval(intervalId);
}
if (timeoutId) {
clearTimeout(timeoutId);
}
// Update Recoil state for completion
setResources((prev) => ({
...prev,
[`${service}-${name}-${identifier}`]: {
...(prev[`${service}-${name}-${identifier}`] || {}),
status: res,
},
}));
}
if (res?.status === 'DOWNLOADED') {
const url = `${getBaseApiReact()}/arbitrary/resource/status/${service}/${name}/${identifier}?build=true`;
const resCall = await fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
});
res = await resCall.json();
}
};
callFunction();
intervalId = setInterval(async () => {
callFunction();
}, 5000);
} catch (error) {
console.error('Error during resource fetch:', error);
}
},
[setResources]
);
return downloadResource;
};