mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-01-09 15:17:59 -05:00
fix(frontend/builder): automatically frame agent when opening in builder (#11640)
## Summary - Fixed auto-frame timing in new builder - now calls `fitView` after nodes are rendered instead of on mount - Replaced manual viewport calculation in legacy builder with React Flow's `fitView` for consistency - Both builders now properly center and frame all blocks when opening an agent ## Test plan - [x] Open an existing agent with multiple blocks in the new builder - verify all blocks are visible and centered - [x] Open an existing agent in the legacy builder - verify all blocks are visible and centered - [x] Verify the manual "Frame" button still works correctly
This commit is contained in:
@@ -20,6 +20,7 @@ import { AgentExecutionStatus } from "@/app/api/__generated__/models/agentExecut
|
||||
|
||||
export const useFlow = () => {
|
||||
const [isLocked, setIsLocked] = useState(false);
|
||||
const [hasAutoFramed, setHasAutoFramed] = useState(false);
|
||||
const addNodes = useNodeStore(useShallow((state) => state.addNodes));
|
||||
const addLinks = useEdgeStore(useShallow((state) => state.addLinks));
|
||||
const updateNodeStatus = useNodeStore(
|
||||
@@ -187,9 +188,36 @@ export const useFlow = () => {
|
||||
};
|
||||
}, []);
|
||||
|
||||
const linkCount = graph?.links?.length ?? 0;
|
||||
|
||||
useEffect(() => {
|
||||
fitView({ padding: 0.2, duration: 800, maxZoom: 2 });
|
||||
}, [fitView]);
|
||||
if (isGraphLoading || isBlocksLoading) {
|
||||
setHasAutoFramed(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (hasAutoFramed) {
|
||||
return;
|
||||
}
|
||||
|
||||
const rafId = requestAnimationFrame(() => {
|
||||
fitView({ padding: 0.2, duration: 800, maxZoom: 1 });
|
||||
setHasAutoFramed(true);
|
||||
});
|
||||
|
||||
return () => cancelAnimationFrame(rafId);
|
||||
}, [
|
||||
fitView,
|
||||
hasAutoFramed,
|
||||
customNodes.length,
|
||||
isBlocksLoading,
|
||||
isGraphLoading,
|
||||
linkCount,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
setHasAutoFramed(false);
|
||||
}, [flowID, flowVersion]);
|
||||
|
||||
// Drag and drop block from block menu
|
||||
const onDragOver = useCallback((event: React.DragEvent) => {
|
||||
|
||||
@@ -103,6 +103,7 @@ const FlowEditor: React.FC<{
|
||||
updateNode,
|
||||
getViewport,
|
||||
setViewport,
|
||||
fitView,
|
||||
screenToFlowPosition,
|
||||
} = useReactFlow<CustomNode, CustomEdge>();
|
||||
const [nodeId, setNodeId] = useState<number>(1);
|
||||
@@ -115,6 +116,7 @@ const FlowEditor: React.FC<{
|
||||
const [pinBlocksPopover, setPinBlocksPopover] = useState(false);
|
||||
// State to control if save popover should be pinned open
|
||||
const [pinSavePopover, setPinSavePopover] = useState(false);
|
||||
const [hasAutoFramed, setHasAutoFramed] = useState(false);
|
||||
|
||||
const {
|
||||
agentName,
|
||||
@@ -482,35 +484,26 @@ const FlowEditor: React.FC<{
|
||||
return uuidv4();
|
||||
}, []);
|
||||
|
||||
// Set the initial view port to center the canvas.
|
||||
useEffect(() => {
|
||||
const { x, y } = getViewport();
|
||||
if (nodes.length <= 0 || x !== 0 || y !== 0) {
|
||||
if (nodes.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const topLeft = { x: Infinity, y: Infinity };
|
||||
const bottomRight = { x: -Infinity, y: -Infinity };
|
||||
if (hasAutoFramed) {
|
||||
return;
|
||||
}
|
||||
|
||||
nodes.forEach((node) => {
|
||||
const { x, y } = node.position;
|
||||
topLeft.x = Math.min(topLeft.x, x);
|
||||
topLeft.y = Math.min(topLeft.y, y);
|
||||
// Rough estimate of the width and height of the node: 500x400.
|
||||
bottomRight.x = Math.max(bottomRight.x, x + 500);
|
||||
bottomRight.y = Math.max(bottomRight.y, y + 400);
|
||||
const rafId = requestAnimationFrame(() => {
|
||||
fitView({ padding: 0.2, duration: 800, maxZoom: 1 });
|
||||
setHasAutoFramed(true);
|
||||
});
|
||||
|
||||
const centerX = (topLeft.x + bottomRight.x) / 2;
|
||||
const centerY = (topLeft.y + bottomRight.y) / 2;
|
||||
const zoom = 0.8;
|
||||
return () => cancelAnimationFrame(rafId);
|
||||
}, [fitView, hasAutoFramed, nodes.length]);
|
||||
|
||||
setViewport({
|
||||
x: window.innerWidth / 2 - centerX * zoom,
|
||||
y: window.innerHeight / 2 - centerY * zoom,
|
||||
zoom: zoom,
|
||||
});
|
||||
}, [nodes, getViewport, setViewport]);
|
||||
useEffect(() => {
|
||||
setHasAutoFramed(false);
|
||||
}, [flowID, flowVersion]);
|
||||
|
||||
const navigateToNode = useCallback(
|
||||
(nodeId: string) => {
|
||||
|
||||
Reference in New Issue
Block a user