diff --git a/src/components/CanvasEmbed.tsx b/src/components/CanvasEmbed.tsx index 6eb6f0e..3cf19d8 100644 --- a/src/components/CanvasEmbed.tsx +++ b/src/components/CanvasEmbed.tsx @@ -1,14 +1,31 @@ 'use client'; +import { useEffect, useCallback } from 'react'; +import { isCanvasMessage, CanvasShapeMessage } from '@/lib/canvas-sync'; + interface CanvasEmbedProps { canvasSlug: string; className?: string; + onShapeUpdate?: (message: CanvasShapeMessage) => void; } -export function CanvasEmbed({ canvasSlug, className = '' }: CanvasEmbedProps) { - const rspaceUrl = process.env.NEXT_PUBLIC_RSPACE_URL || 'https://rspace.online'; +export function CanvasEmbed({ canvasSlug, className = '', onShapeUpdate }: CanvasEmbedProps) { const canvasUrl = `https://${canvasSlug}.rspace.online`; + const handleMessage = useCallback( + (event: MessageEvent) => { + if (!isCanvasMessage(event)) return; + if (event.data.communitySlug !== canvasSlug) return; + onShapeUpdate?.(event.data); + }, + [canvasSlug, onShapeUpdate] + ); + + useEffect(() => { + window.addEventListener('message', handleMessage); + return () => window.removeEventListener('message', handleMessage); + }, [handleMessage]); + return (
{/* Toolbar */} diff --git a/src/lib/canvas-sync.ts b/src/lib/canvas-sync.ts new file mode 100644 index 0000000..2dddef8 --- /dev/null +++ b/src/lib/canvas-sync.ts @@ -0,0 +1,40 @@ +/** + * Canvas sync utilities for rtrips.online <-> rspace.online integration + * + * Listens for postMessage events from the embedded rspace canvas iframe + * and provides methods to push structured data to the canvas. + */ + +export interface CanvasShapeMessage { + source: 'rspace-canvas'; + type: 'shape-updated' | 'shape-deleted'; + communitySlug: string; + shapeId: string; + data: Record; +} + +export function isCanvasMessage(event: MessageEvent): event is MessageEvent { + return event.data?.source === 'rspace-canvas'; +} + +/** + * Push shapes to an rspace canvas community via the shapes API + */ +export async function pushShapesToCanvas( + canvasSlug: string, + shapes: Record[], + rspaceUrl?: string +): Promise { + const baseUrl = rspaceUrl || process.env.RSPACE_INTERNAL_URL || 'http://rspace-online:3000'; + + const response = await fetch(`${baseUrl}/api/communities/${canvasSlug}/shapes`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ shapes }), + }); + + if (!response.ok) { + const text = await response.text(); + throw new Error(`Failed to push shapes: ${response.status} ${text}`); + } +}