diff --git a/src/app/page.tsx b/src/app/page.tsx index d35b1b2..3112b11 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -55,6 +55,12 @@ const shapeUtils = [LiveImageShapeUtil] const tools = [LiveImageTool] export default function Home() { + // Server-side rendering check + if (typeof window === 'undefined') { + // Return a minimal placeholder for SSR + return
Loading editor...
+ } + const onEditorMount = (editor: Editor) => { // We need the editor to think that the live image shape is a frame // @ts-expect-error: patch diff --git a/src/hooks/useLiveImage.tsx b/src/hooks/useLiveImage.tsx index c13607a..d52221b 100644 --- a/src/hooks/useLiveImage.tsx +++ b/src/hooks/useLiveImage.tsx @@ -121,6 +121,9 @@ export function useLiveImage( if (!fetchImage) throw new Error('Missing LiveImageProvider') useEffect(() => { + // Skip on server-side + if (typeof window === 'undefined') return; + let prevHash = '' let prevPrompt = '' diff --git a/src/utils/screenshot.ts b/src/utils/screenshot.ts index 378a249..91a39db 100644 --- a/src/utils/screenshot.ts +++ b/src/utils/screenshot.ts @@ -1,11 +1,21 @@ -import { type } from 'os' +'use client' -const fileReader = new FileReader() +import { type } from 'os' +import { blobToDataUri } from './blob' let _canvas: HTMLCanvasElement | null = null let _ctx: CanvasRenderingContext2D | null = null +function getFileReader() { + if (typeof window === 'undefined') return null + return new FileReader() +} + async function fastGetSvgAsString(svg: SVGElement) { + if (typeof window === 'undefined') { + return '' + } + const clone = svg.cloneNode(true) as SVGGraphicsElement svg.setAttribute('width', +svg.getAttribute('width')! + '') @@ -17,13 +27,13 @@ async function fastGetSvgAsString(svg: SVGElement) { const src = img.getAttribute('xlink:href') if (src) { if (!src.startsWith('data:')) { - const blob = await (await fetch(src)).blob() - const base64 = await new Promise((resolve, reject) => { - fileReader.onload = () => resolve(fileReader.result as string) - fileReader.onerror = () => reject(fileReader.error) - fileReader.readAsDataURL(blob) - }) - img.setAttribute('xlink:href', base64) + try { + const blob = await (await fetch(src)).blob() + const base64 = await blobToDataUri(blob) + img.setAttribute('xlink:href', base64) + } catch (error) { + console.error('Error processing image:', error) + } } } } @@ -45,6 +55,10 @@ export async function fastGetSvgAsImage( height: number } ) { + if (typeof window === 'undefined') { + return null + } + const svgUrl = URL.createObjectURL(new Blob([svgString], { type: 'image/svg+xml' })) if (!_canvas) { @@ -84,18 +98,13 @@ export async function fastGetSvgAsImage( if (!canvas) return null - const blobPromise = new Promise((resolve) => + return new Promise((resolve) => canvas.toBlob( (blob) => { - if (!blob) { - resolve(null) - } resolve(blob) }, - 'image/' + type, + `image/${options.type}`, options.quality ) ) - - return blobPromise }