import { useCallback } from 'react' import { Box, TldrawUiButton, TldrawUiButtonIcon, TldrawUiButtonLabel, useEditor, useValue, Vec, } from 'tldraw' import { TldrawAgent } from '../agent/TldrawAgent' import { useAgents } from '../agent/TldrawAgentAppProvider' /** * Renders GoToAgentButton for all agents. */ export function GoToAgentButtons() { const agents = useAgents() return ( <> {agents.map((agent) => ( ))} ) } /** * A button that zooms the viewport to show where an agent is working. */ export function GoToAgentButton({ agent }: { agent: TldrawAgent }) { const editor = useEditor() const currentRequest = useValue('activeRequest', () => agent.requests.getActiveRequest(), [agent]) const agentViewport = currentRequest?.bounds // We only show the button if the agent is offscreen const agentIsOffscreen = useValue( 'agentIsOffscreen', () => { if (!agentViewport) return false const screenBounds = editor.getViewportScreenBounds() const agentViewportScreenCorners = Box.From(agentViewport).corners.map((corner) => editor.pageToViewport(corner) ) return !Box.FromPoints(agentViewportScreenCorners).collides(screenBounds) }, [agentViewport] ) // The button's arrow points towards the agent const angleToAgent = useValue( 'angleToAgent', () => { if (!agentViewport) return if (agentIsOffscreen) return const agentCenter = Box.From(agentViewport).center const agentScreenCenter = editor.pageToViewport(agentCenter) const screenBounds = editor.getViewportScreenBounds() const screenCenter = Box.From(screenBounds).center const displacement = Vec.From(agentScreenCenter).sub(screenCenter) return Math.atan2(displacement.y, displacement.x) * (180 / Math.PI) }, [agentViewport] ) const handleClick = useCallback(() => { if (agentViewport) { const bounds = Box.From(agentViewport).expandBy(50) editor.zoomToBounds(bounds, { animation: { duration: 220 } }) } }, [agentViewport, editor]) if (!agentViewport) return null if (!agentIsOffscreen) return null return (
} /> Go to {agent.id}
) }