tfrere's picture
tfrere HF Staff
update story
78b81a5
import { useCallback } from "react";
import { useScreenshot } from "use-react-screenshot";
export function useStoryCapture() {
const [image, takeScreenshot] = useScreenshot({
type: "image/png",
quality: 1.0,
});
const calculateOptimalWidth = (element) => {
// Get all comic pages
const comicPages = element.querySelectorAll("[data-comic-page]");
if (!comicPages.length) return element.scrollWidth;
// Get width of a single page (they all have the same width)
const firstPage = comicPages[0];
const pageWidth = firstPage.offsetWidth;
const gap = 32; // Fixed gap between pages
const padding = 32; // Fixed padding on both sides
// Calculate total width:
// - All pages width (pageWidth * nbPages)
// - Gaps only between pages, so (nbPages - 1) gaps
// - Padding on both sides
const totalWidth =
pageWidth * comicPages.length +
(comicPages.length > 1 ? gap * (comicPages.length - 1) : 0) +
padding * 2;
console.log("Width calculation:", {
numberOfPages: comicPages.length,
pageWidth,
gapBetweenPages: gap,
totalGaps: comicPages.length > 1 ? gap * (comicPages.length - 1) : 0,
padding,
totalWidth,
});
return totalWidth;
};
const captureStory = useCallback(
async (containerRef) => {
if (!containerRef.current) return null;
const element = containerRef.current.querySelector("[data-comic-layout]");
if (!element) {
console.error("Comic layout container not found");
return null;
}
try {
// Save original styles
const originalStyle = element.style.cssText;
const originalScroll = element.scrollLeft;
const originalWidth = element.style.width;
const originalPadding = element.style.padding;
const originalGap = element.style.gap;
// Calculate optimal width
const optimalWidth = calculateOptimalWidth(element);
// Reset scroll and styles temporarily for the screenshot
Object.assign(element.style, {
width: `${optimalWidth}px`,
display: "flex",
flexDirection: "row",
gap: "32px",
padding: "32px",
paddingLeft: "32px !important", // Force override the dynamic padding
paddingRight: "32px !important", // Force override the dynamic padding
overflow: "hidden",
transition: "none", // Disable transitions during capture
});
element.scrollLeft = 0;
// Force reflow
element.offsetHeight;
// Take screenshot
const result = await takeScreenshot(element, {
backgroundColor: "#242424",
width: optimalWidth,
height: element.scrollHeight,
style: {
transform: "none",
transition: "none",
},
});
// Restore original styles
element.style.cssText = originalStyle;
element.style.width = originalWidth;
element.style.padding = originalPadding;
element.style.gap = originalGap;
element.scrollLeft = originalScroll;
return result;
} catch (error) {
console.error("Error capturing story:", error);
return null;
}
},
[takeScreenshot]
);
const downloadStoryImage = useCallback(
async (containerRef, filename = "my-story.png") => {
const image = await captureStory(containerRef);
if (!image) return;
const link = document.createElement("a");
link.href = image;
link.download = filename;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
},
[captureStory]
);
return {
captureStory,
downloadStoryImage,
};
}