mirror of
https://github.com/Qortal/qapp-core.git
synced 2025-06-14 17:41:20 +00:00
212 lines
6.4 KiB
TypeScript
212 lines
6.4 KiB
TypeScript
import React, { useCallback, useEffect, useMemo, useRef } from "react";
|
|
import { ResourceStatus, usePublishStore } from "../state/publishes";
|
|
import { QortalGetMetadata } from "../types/interfaces/resources";
|
|
|
|
interface PropsUseResourceStatus {
|
|
resource: QortalGetMetadata | null;
|
|
retryAttempts?: number;
|
|
}
|
|
export const useResourceStatus = ({
|
|
resource,
|
|
retryAttempts = 50,
|
|
}: PropsUseResourceStatus) => {
|
|
const resourceId = !resource ? null : `${resource.service}-${resource.name}-${resource.identifier}`;
|
|
const status = usePublishStore((state)=> state.getResourceStatus(resourceId)) || null
|
|
const intervalRef = useRef<null | number>(null)
|
|
const timeoutRef = useRef<null | number>(null)
|
|
const setResourceStatus = usePublishStore((state) => state.setResourceStatus);
|
|
const statusRef = useRef<ResourceStatus | null>(null)
|
|
|
|
useEffect(()=> {
|
|
statusRef.current = status
|
|
}, [status])
|
|
const downloadResource = useCallback(
|
|
({ service, name, identifier }: QortalGetMetadata, build?: boolean) => {
|
|
try {
|
|
if(statusRef.current && statusRef.current?.status === 'READY'){
|
|
if (intervalRef.current) {
|
|
clearInterval(intervalRef.current);
|
|
}
|
|
if (timeoutRef.current) {
|
|
clearTimeout(timeoutRef.current);
|
|
}
|
|
return
|
|
}
|
|
setResourceStatus(
|
|
{ service, name, identifier },
|
|
{
|
|
"status": "SEARCHING",
|
|
"localChunkCount": 0,
|
|
"totalChunkCount": 0,
|
|
"percentLoaded": 0
|
|
}
|
|
);
|
|
let isCalling = false;
|
|
let percentLoaded = 0;
|
|
let timer = 24;
|
|
let tries = 0;
|
|
let calledFirstTime = false;
|
|
const callFunction = async () => {
|
|
if (isCalling) return;
|
|
isCalling = true;
|
|
|
|
let res;
|
|
if (!build) {
|
|
const urlFirstTime = `/arbitrary/resource/status/${service}/${name}/${identifier}`;
|
|
const resCall = await fetch(urlFirstTime, {
|
|
method: "GET",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
});
|
|
res = await resCall.json();
|
|
setResourceStatus(
|
|
{ service, name, identifier },
|
|
{
|
|
...res
|
|
}
|
|
);
|
|
if (tries > retryAttempts) {
|
|
if (intervalRef.current) {
|
|
clearInterval(intervalRef.current);
|
|
}
|
|
if (timeoutRef.current) {
|
|
clearTimeout(timeoutRef.current);
|
|
}
|
|
setResourceStatus(
|
|
{ service, name, identifier },
|
|
{
|
|
...res,
|
|
status: "FAILED_TO_DOWNLOAD",
|
|
}
|
|
);
|
|
|
|
return;
|
|
}
|
|
tries = tries + 1;
|
|
}
|
|
|
|
if (build || (calledFirstTime === false && res?.status !== "READY")) {
|
|
const url = `/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;
|
|
|
|
setResourceStatus(
|
|
{ service, name, identifier },
|
|
{
|
|
...res,
|
|
status: "REFETCHING",
|
|
}
|
|
);
|
|
|
|
timeoutRef.current = setTimeout(() => {
|
|
isCalling = false;
|
|
downloadResource({ name, service, identifier }, true);
|
|
}, 25000);
|
|
|
|
return;
|
|
}
|
|
|
|
percentLoaded = res.percentLoaded;
|
|
}
|
|
|
|
setResourceStatus(
|
|
{ service, name, identifier },
|
|
{
|
|
...res,
|
|
}
|
|
);
|
|
}
|
|
|
|
// Check if progress is 100% and clear interval if true
|
|
if (res?.status === "READY") {
|
|
if (intervalRef.current) {
|
|
clearInterval(intervalRef.current);
|
|
}
|
|
if (timeoutRef.current) {
|
|
clearTimeout(timeoutRef.current);
|
|
}
|
|
setResourceStatus({service, name, identifier}, {
|
|
...res,
|
|
})
|
|
}
|
|
if (res?.status === "DOWNLOADED") {
|
|
const url = `/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();
|
|
intervalRef.current = setInterval(async () => {
|
|
callFunction();
|
|
}, 5000);
|
|
} catch (error) {
|
|
console.error("Error during resource fetch:", error);
|
|
}
|
|
},
|
|
[retryAttempts]
|
|
);
|
|
useEffect(() => {
|
|
if (resource?.identifier && resource?.name && resource?.service) {
|
|
downloadResource({
|
|
service: resource?.service,
|
|
name: resource?.name,
|
|
identifier: resource?.identifier,
|
|
});
|
|
}
|
|
return ()=> {
|
|
if(intervalRef.current){
|
|
clearInterval(intervalRef.current)
|
|
}
|
|
if(timeoutRef.current){
|
|
clearTimeout(timeoutRef.current)
|
|
}
|
|
}
|
|
}, [
|
|
resource?.identifier,
|
|
resource?.name,
|
|
resource?.service,
|
|
downloadResource,
|
|
]);
|
|
|
|
const resourceUrl = resource ? `/arbitrary/${resource.service}/${resource.name}/${resource.identifier}` : null;
|
|
|
|
return useMemo(() => ({
|
|
status: status?.status || "SEARCHING",
|
|
localChunkCount: status?.localChunkCount || 0,
|
|
totalChunkCount: status?.totalChunkCount || 0,
|
|
percentLoaded: status?.percentLoaded || 0,
|
|
isReady: status?.status === 'READY',
|
|
resourceUrl,
|
|
}), [status?.status, status?.localChunkCount, status?.totalChunkCount, status?.percentLoaded, resourceUrl]);
|
|
|
|
};
|