import React, { ReactElement, useCallback, useEffect, useState } from "react"; import { DnD } from "../../shared/Draggable/DnD"; import { isEmpty } from "lodash"; import SlidingPane from "react-sliding-pane"; import { Canvas } from "../../shared/Canvas"; import { useQuery, useQueryClient } from "@tanstack/react-query"; import axios from "axios"; import { IMAGETRANSFORMATION_SERVICE_BASE_URI, LIBRARY_SERVICE_BASE_URI, LIBRARY_SERVICE_HOST, } from "../../../constants/endpoints"; import { useStore } from "../../../store"; import { useShallow } from "zustand/react/shallow"; import { escapePoundSymbol } from "../../../shared/utils/formatting.utils"; export const ArchiveOperations = (props: { data: any }): ReactElement => { const { data } = props; const getSocket = useStore((state) => state.getSocket); const queryClient = useQueryClient(); // sliding panel config const [visible, setVisible] = useState(false); const [slidingPanelContentId, setSlidingPanelContentId] = useState(""); // current image const [currentImage, setCurrentImage] = useState(""); const [uncompressedArchive, setUncompressedArchive] = useState([]); const [imageAnalysisResult, setImageAnalysisResult] = useState({}); const [shouldRefetchComicBookData, setShouldRefetchComicBookData] = useState(false); const constructImagePaths = (data: string[]): Array => { return data?.map((path: string) => escapePoundSymbol(encodeURI(`${LIBRARY_SERVICE_HOST}/${path}`)), ); }; // Listen to the uncompression complete event and orchestrate the final payload useEffect(() => { const socket = getSocket("/"); if (!socket) return; const handleUncompressionComplete = (data: any) => { setUncompressedArchive(constructImagePaths(data?.uncompressedArchive)); }; socket.on("LS_UNCOMPRESSION_JOB_COMPLETE", handleUncompressionComplete); return () => { socket.off("LS_UNCOMPRESSION_JOB_COMPLETE", handleUncompressionComplete); }; }, [getSocket]); useEffect(() => { let isMounted = true; if (data.rawFileDetails?.archive?.uncompressed) { const fetchUncompressedArchive = async () => { try { const response = await axios({ url: `${LIBRARY_SERVICE_BASE_URI}/walkFolders`, method: "POST", data: { basePathToWalk: data?.rawFileDetails?.archive?.expandedPath, extensions: [".jpg", ".jpeg", ".png", ".bmp", "gif"], }, transformResponse: async (responseData) => { const parsedData = JSON.parse(responseData); const paths = parsedData.map((pathObject: any) => { return `${pathObject.containedIn}/${pathObject.name}${pathObject.extension}`; }); const uncompressedArchive = constructImagePaths(paths); if (isMounted) { setUncompressedArchive(uncompressedArchive); setShouldRefetchComicBookData(true); } }, }); } catch (error) { // Error handling could be added here if needed } }; fetchUncompressedArchive(); } // Cleanup function return () => { isMounted = false; setUncompressedArchive([]); }; }, [data]); const analyzeImage = async (imageFilePath: string) => { const response = await axios({ url: `${IMAGETRANSFORMATION_SERVICE_BASE_URI}/analyze`, method: "POST", data: { imageFilePath, }, }); setImageAnalysisResult(response?.data); queryClient.invalidateQueries({ queryKey: ["uncompressedArchive"] }); }; const { data: uncompressionResult, refetch, isLoading, isSuccess, } = useQuery({ queryFn: async () => await axios({ method: "POST", url: `http://localhost:3000/api/library/uncompressFullArchive`, headers: { "Content-Type": "application/json; charset=utf-8", }, data: { filePath: data.rawFileDetails.filePath, comicObjectId: data._id, options: { type: "full", purpose: "analysis", imageResizeOptions: { baseWidth: 275, }, }, }, }), queryKey: ["uncompressedArchive"], enabled: false, }); useEffect(() => { if (isSuccess && shouldRefetchComicBookData) { queryClient.invalidateQueries({ queryKey: ["comicBookMetadata"] }); setShouldRefetchComicBookData(false); } }, [isSuccess, shouldRefetchComicBookData, queryClient]); // sliding panel init const contentForSlidingPanel: Record JSX.Element }> = { imageAnalysis: { content: () => { return (
{currentImage}
{!isEmpty(imageAnalysisResult) ? (
                
              
) : null}
              {JSON.stringify(imageAnalysisResult?.analyzedData, null, 2)}
            
); }, }, }; // sliding panel handlers const openImageAnalysisPanel = useCallback((imageFilePath: string) => { setSlidingPanelContentId("imageAnalysis"); analyzeImage(imageFilePath); setCurrentImage(imageFilePath); setVisible(true); }, []); return (

You can perform several operations on your comic book archive.

Uncompressing, re-organizing the individual pages, then re-compressing to a different format, for example.

You can also analyze color histograms of pages.

{data.rawFileDetails.archive?.uncompressed && !isEmpty(uncompressedArchive) ? (
This issue is already uncompressed at:

{data.rawFileDetails.archive.expandedPath}

It has {uncompressedArchive?.length} pages

) : null}
{isEmpty(uncompressedArchive) ? ( ) : null} {!isEmpty(uncompressedArchive) ? (
) : null}
{!isEmpty(uncompressedArchive) ? ( ) : null}
setVisible(false)} title={"Image Analysis"} width={"600px"} > {slidingPanelContentId !== "" && contentForSlidingPanel[slidingPanelContentId].content()}
); }; export default ArchiveOperations;