feat: when restored position has no nodes in viewport, automatically fit to view (#7435)

## Summary

Sometimes the saved position is super far away from any of the nodes,
which causes general confusion. This PR changes the `loadGraphData`
logic to fit-to-view in those scenarios.

Fixes https://github.com/Comfy-Org/ComfyUI_frontend/issues/7425

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7435-feat-when-restored-position-has-no-nodes-in-viewport-automatically-fit-to-view-2c86d73d36508119bf2ed9d361ec868f)
by [Unito](https://www.unito.io)

---------

Co-authored-by: github-actions <github-actions@github.com>
This commit is contained in:
Christian Byrne
2025-12-17 15:38:05 -08:00
committed by GitHub
parent db929220af
commit 1d014c0dbe
5 changed files with 473 additions and 6 deletions

View File

@@ -1,6 +1,9 @@
import type { ReadOnlyRect } from '@/lib/litegraph/src/interfaces'
import type { Bounds } from '@/renderer/core/layout/types'
/** Simple 2D point or size as [x, y] or [width, height] */
type Vec2 = readonly [number, number]
/**
* Finds the greatest common divisor (GCD) for two numbers using iterative
* Euclidean algorithm. Uses iteration instead of recursion to avoid stack
@@ -91,3 +94,28 @@ export function computeUnionBounds(
height: maxY - minY
}
}
/**
* Checks if any item with pos/size overlaps a rectangle (AABB test).
* @param items Items with pos [x, y] and size [width, height]
* @param rect Rectangle as [x, y, width, height]
* @returns `true` if any item overlaps the rect
*/
export function anyItemOverlapsRect(
items: Iterable<{ pos: Vec2; size: Vec2 }>,
rect: ReadOnlyRect
): boolean {
const rectRight = rect[0] + rect[2]
const rectBottom = rect[1] + rect[3]
for (const item of items) {
const overlaps =
item.pos[0] < rectRight &&
item.pos[0] + item.size[0] > rect[0] &&
item.pos[1] < rectBottom &&
item.pos[1] + item.size[1] > rect[1]
if (overlaps) return true
}
return false
}