diff --git a/client/src/components/document-editor/document-editor-local.component.jsx b/client/src/components/document-editor/document-editor-local.component.jsx index b1511352a..18bf0ead8 100644 --- a/client/src/components/document-editor/document-editor-local.component.jsx +++ b/client/src/components/document-editor/document-editor-local.component.jsx @@ -97,41 +97,45 @@ export function DocumentEditorLocalComponent({ imageUrl, filename, jobid }) { }, [triggerUpload, imageLoaded]); useEffect(() => { - // Load the image from imageUrl - let isCancelled = false; + if (!imageUrl) return; + const controller = new AbortController(); const loadImage = async () => { - if (!imageUrl) return; - setImageLoaded(false); setImageLoading(true); - try { - const response = await axios.get(imageUrl, { responseType: "blob" }); - - if (isCancelled) return; - + const response = await axios.get(imageUrl, { responseType: "blob", signal: controller.signal }); const blobUrl = URL.createObjectURL(response.data); setLoadedImageUrl((prevUrl) => { if (prevUrl) URL.revokeObjectURL(prevUrl); return blobUrl; }); } catch (error) { + if (axios.isCancel?.(error) || error.name === "CanceledError") { + // request was aborted — safe to ignore + return; + } console.error("Failed to fetch image blob", error); } finally { - if (!isCancelled) { + if (!controller.signal.aborted) { setImageLoading(false); } } }; - loadImage(); - return () => { - isCancelled = true; + controller.abort(); }; }, [imageUrl]); + useEffect(() => { + return () => { + if (loadedImageUrl) { + URL.revokeObjectURL(loadedImageUrl); + } + }; + }, [loadedImageUrl]); + async function b64toBlob(url) { const res = await fetch(url); return await res.blob(); diff --git a/client/src/components/document-editor/document-editor.component.jsx b/client/src/components/document-editor/document-editor.component.jsx index 8df1be57f..1bdf0f9e7 100644 --- a/client/src/components/document-editor/document-editor.component.jsx +++ b/client/src/components/document-editor/document-editor.component.jsx @@ -84,45 +84,50 @@ export function DocumentEditorComponent({ currentUser, bodyshop, document }) { }, [triggerUpload, imageLoaded]); useEffect(() => { - // When the document changes, fetch the image via axios so auth and base URL are applied - let isCancelled = false; + if (!document?.id) return; + const controller = new AbortController(); const loadImage = async () => { - if (!document || !document.id) return; - setImageLoaded(false); setImageLoading(true); - try { const response = await axios.post( "/media/imgproxy/original", { documentId: document.id }, - { responseType: "blob" } + { + responseType: "blob", + signal: controller.signal + } ); - - if (isCancelled) return; - const blobUrl = URL.createObjectURL(response.data); setImageUrl((prevUrl) => { if (prevUrl) URL.revokeObjectURL(prevUrl); return blobUrl; }); } catch (error) { + if (axios.isCancel?.(error) || error.name === "CanceledError") { + // request was aborted — safe to ignore + return; + } console.error("Failed to fetch original image blob", error); } finally { - if (!isCancelled) { - setImageLoading(false); - } + setImageLoading(false); } }; - loadImage(); - return () => { - isCancelled = true; + controller.abort(); }; }, [document]); + useEffect(() => { + return () => { + if (imageUrl) { + URL.revokeObjectURL(imageUrl); + } + }; + }, [imageUrl]); + async function b64toBlob(url) { const res = await fetch(url); return await res.blob(); diff --git a/client/src/components/document-editor/document-editor.container.jsx b/client/src/components/document-editor/document-editor.container.jsx index e10483694..ed2736d09 100644 --- a/client/src/components/document-editor/document-editor.container.jsx +++ b/client/src/components/document-editor/document-editor.container.jsx @@ -33,6 +33,19 @@ export function DocumentEditorContainer({ setBodyshop }) { nextFetchPolicy: "network-only" }); + const isLocalMedia = !!dataShop?.bodyshops?.[0]?.uselocalmediaserver; + + const { + loading: loadingDoc, + error: errorDoc, + data: dataDoc + } = useQuery(GET_DOCUMENT_BY_PK, { + variables: { documentId }, + skip: !documentId || isLocalMedia, + fetchPolicy: "network-only", + nextFetchPolicy: "network-only" + }); + useEffect(() => { if (dataShop) setBodyshop(dataShop.bodyshops[0]); }, [dataShop, setBodyshop]); @@ -40,7 +53,7 @@ export function DocumentEditorContainer({ setBodyshop }) { if (loadingShop) return ; if (errorShop) return ; - if (dataShop?.bodyshops[0]?.uselocalmediaserver) { + if (isLocalMedia) { if (imageUrl && filename && jobid) { return (
@@ -52,20 +65,13 @@ export function DocumentEditorContainer({ setBodyshop }) { } } - const { loading, error, data } = useQuery(GET_DOCUMENT_BY_PK, { - variables: { documentId }, - skip: !documentId, - fetchPolicy: "network-only", - nextFetchPolicy: "network-only" - }); + if (loadingDoc) return ; + if (errorDoc) return ; - if (loading) return ; - if (error) return ; - - if (!data || !data.documents_by_pk) return ; + if (!dataDoc || !dataDoc.documents_by_pk) return ; return (
- +
); } diff --git a/client/src/components/jobs-documents-local-gallery/jobs-documents-local-gallery.container.jsx b/client/src/components/jobs-documents-local-gallery/jobs-documents-local-gallery.container.jsx index da9274eef..da94678a8 100644 --- a/client/src/components/jobs-documents-local-gallery/jobs-documents-local-gallery.container.jsx +++ b/client/src/components/jobs-documents-local-gallery/jobs-documents-local-gallery.container.jsx @@ -190,7 +190,7 @@ export function JobsDocumentsLocalGallery({ key="edit" onClick={() => { const newWindow = window.open( - `${window.location.protocol}//${window.location.host}/edit-local?imageUrl=${ + `${window.location.protocol}//${window.location.host}/edit?imageUrl=${ jobMedia.images[modalState.index].fullsize }&filename=${jobMedia.images[modalState.index].filename}&jobid=${job.id}`, "_blank",